util.c (50691B)
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 * General utility routines 8 */ 9 10 #include <assert.h> 11 12 #include <shared/bsl.h> 13 #include <shared/util.h> 14 #include <shared/l3.h> 15 #include <shared/error.h> 16 #include <soc/error.h> 17 18 #include <sal/types.h> 19 #include <sal/core/libc.h> 20 21 #define RDPC_MUTEX_TIMEOUT (100000) 22 23 /* 24 * Swap the bytes in a 32-bit word 25 */ 26 27 STATIC INLINE unsigned int 28 __shr_swap32(unsigned int i) 29 { 30 i = (i << 16) | (i >> 16); 31 32 return (i & 0xff00ffff) >> 8 | (i & 0xffff00ff) << 8; 33 } 34 35 unsigned int 36 _shr_swap32(unsigned int i) 37 { 38 return __shr_swap32(i); 39 } 40 41 /* 42 * Swap the bytes in a 16-bit half-word 43 */ 44 45 STATIC INLINE unsigned short 46 __shr_swap16(unsigned short i) 47 { 48 return i << 8 | i >> 8; 49 } 50 51 unsigned short 52 _shr_swap16(unsigned short i) 53 { 54 return __shr_swap16(i); 55 } 56 57 /* 58 * Return the number of bits set in a unsigned int 59 */ 60 61 int 62 _shr_popcount(unsigned int n) 63 { 64 n = (n & 0x55555555) + ((n >> 1) & 0x55555555); 65 n = (n & 0x33333333) + ((n >> 2) & 0x33333333); 66 n = (n + (n >> 4)) & 0x0f0f0f0f; 67 n = n + (n >> 8); 68 69 return (n + (n >> 16)) & 0xff; 70 } 71 72 /* 73 * A few bit twiddling routines, initially for hashing 74 */ 75 76 /* reverse the bits in an 8 bit byte */ 77 uint8 78 _shr_bit_rev8(uint8 n) 79 { 80 n = (((n & 0xaa) >> 1) | ((n & 0x55) << 1)); 81 n = (((n & 0xcc) >> 2) | ((n & 0x33) << 2)); 82 n = (((n & 0xf0) >> 4) | ((n & 0x0f) << 4)); 83 return n; 84 } 85 86 87 /* reverse the bits in an 16 bit short */ 88 uint16 89 _shr_bit_rev16(uint16 n) 90 { 91 n = (((n & 0xaaaa) >> 1) | ((n & 0x5555) << 1)); 92 n = (((n & 0xcccc) >> 2) | ((n & 0x3333) << 2)); 93 n = (((n & 0xf0f0) >> 4) | ((n & 0x0f0f) << 4)); 94 n = (((n & 0xff00) >> 8) | ((n & 0x00ff) << 8)); 95 return n; 96 } 97 98 /* reverse the bits in an 32 bit long */ 99 uint32 100 _shr_bit_rev32(uint32 n) 101 { 102 n = (((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1)); 103 n = (((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2)); 104 n = (((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4)); 105 n = (((n & 0xff00ff00) >> 8) | ((n & 0x00ff00ff) << 8)); 106 return (n >> 16) | (n << 16); 107 } 108 109 /* reverse the bits in each byte of a 32 bit long */ 110 uint32 111 _shr_bit_rev_by_byte_word32(uint32 n) 112 { 113 n = (((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1)); 114 n = (((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2)); 115 n = (((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4)); 116 return n; 117 } 118 119 /* 120 * Ethernet CRC Algorithm 121 * 122 * To generate CRC, do not include CRC field in data: 123 * unsigned int crc = ~_shr_crc32(~0, data, len) 124 * 125 * To check CRC, include CRC field in data: 126 * unsigned int check = _shr_crc32(~0, data, len) 127 * If CRC is correct, result will be _SHR_CRC32_CORRECT. 128 * 129 * NOTE: This routine generates the same 32-bit value whether the 130 * platform is big- or little-endian. The value must be stored into a 131 * network packet in big-endian order, i.e. using htonl() or equivalent. 132 * (Polynomial x ^ 32 + x ^ 28 + x ^ 23 + x ^ 22 + x ^ 16 + x ^ 12 + x ^ 11 + 133 * x ^ 10 + x ^ 8 + x ^ 7 + x ^ 5 + x ^ 4 + x ^ 2 + x ^ 1 + 1) 134 */ 135 136 static int _shr_crc_table_inited; 137 static unsigned int _shr_crc_table[256]; 138 139 unsigned int 140 _shr_crc32(unsigned int crc, unsigned char *data, int len) 141 { 142 int i; 143 144 if (!_shr_crc_table_inited) { 145 int j; 146 unsigned int accum; 147 148 for (i = 0; i < 256; i++) { 149 accum = i; 150 151 for (j = 0; j < 8; j++) { 152 if (accum & 1) { 153 accum = accum >> 1 ^ 0xedb88320UL; 154 } else { 155 accum = accum >> 1; 156 } 157 } 158 159 _shr_crc_table[i] = __shr_swap32(accum); 160 } 161 162 _shr_crc_table_inited = 1; 163 } 164 165 for (i = 0; i < len; i++) { 166 crc = crc << 8 ^ _shr_crc_table[crc >> 24 ^ data[i]]; 167 } 168 169 return crc; 170 } 171 172 /* Matches _shr_crc32 above */ 173 unsigned int 174 _shr_crc32b(unsigned int crc, unsigned char *data, int nbits) 175 { 176 int i; 177 int j; 178 unsigned int accum; 179 unsigned int poly = 0xedb88320UL; 180 int last_nbits; 181 182 if (!_shr_crc_table_inited) { 183 for (i = 0; i < 256; i++) { 184 accum = i; 185 186 for (j = 0; j < 8; j++) { 187 accum = (accum & 1) ? (accum >> 1 ^ poly) : (accum >> 1); 188 } 189 _shr_crc_table[i] = __shr_swap32(accum); 190 } 191 _shr_crc_table_inited = 1; 192 } 193 194 for (i = 0; i < (nbits / 8); i++) { 195 crc = (crc << 8) ^ _shr_crc_table[data[i] ^ ((crc >> 24) & 0x000FF)]; 196 } 197 198 last_nbits = nbits % 8; 199 if (last_nbits) { 200 accum = ((crc >> (32 - last_nbits)) & ((1 << last_nbits) - 1)) ^ 201 (data[i] & ((1 << last_nbits) - 1)); 202 for (j = 0; j < last_nbits; j++) { 203 accum = (accum & 1) ? (accum >> 1 ^ poly) : (accum >> 1); 204 } 205 crc = (crc << last_nbits) ^ __shr_swap32(accum); 206 } 207 208 return crc; 209 } 210 211 static int _shr_crc32bd15_table_inited; 212 static unsigned int _shr_crc32bd15_table[256]; 213 214 /* Matches Draco 1.5 CRC32 key76 */ 215 216 unsigned int 217 _shr_crc32bd15(unsigned int crc, unsigned char *data, int nbits) 218 { 219 int i; 220 int j; 221 unsigned int accum; 222 unsigned int poly = 0xedb88320UL; 223 int last_nbits; 224 225 if (!_shr_crc32bd15_table_inited) { 226 for (i = 0; i < 256; i++) { 227 accum = i; 228 229 for (j = 0; j < 8; j++) { 230 accum = (accum & 1) ? (accum >> 1 ^ poly) : (accum >> 1); 231 } 232 _shr_crc32bd15_table[i] = accum; 233 } 234 _shr_crc32bd15_table_inited = 1; 235 } 236 237 for (i = 0; i < (nbits / 8); i++) { 238 crc = (crc >> 8) ^ ((data[i] & 0x000000FF) << 24) ^ 239 _shr_crc32bd15_table[crc & 0x000000FF]; 240 } 241 242 last_nbits = nbits % 8; 243 if (last_nbits) { 244 accum = crc & ((1 << last_nbits) - 1); 245 for (j = 0; j < last_nbits; j++) { 246 accum = (accum & 1) ? (accum >> 1 ^ poly) : (accum >> 1); 247 } 248 crc = (crc >> last_nbits) ^ accum ^ 249 ((data[i] & ((1 << last_nbits) - 1)) << (32 - last_nbits)); 250 } 251 252 return crc; 253 } 254 255 256 /* 257 * CRC16 for Draco (Polynomial x ^ 16 + x ^ 15 + x ^ 2 + 1) 258 */ 259 260 static unsigned short _shr_crc_16_table[16] = { 261 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 262 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400 263 }; 264 265 unsigned short 266 _shr_crc16(int start, unsigned char *p, int n) 267 { 268 unsigned short int crc = start; 269 int r; 270 271 /* while there is more data to process */ 272 while (n-- > 0) { 273 274 /* compute checksum of lower four bits of *p */ 275 r = _shr_crc_16_table[crc & 0xF]; 276 crc = (crc >> 4) & 0x0FFF; 277 crc = crc ^ r ^ _shr_crc_16_table[*p & 0xF]; 278 279 /* now compute checksum of upper four bits of *p */ 280 r = _shr_crc_16_table[crc & 0xF]; 281 crc = (crc >> 4) & 0x0FFF; 282 crc = crc ^ r ^ _shr_crc_16_table[(*p >> 4) & 0xF]; 283 284 /* next... */ 285 p++; 286 } 287 288 return(crc); 289 } 290 291 static int _shr_crc16b_table_inited; 292 static unsigned int _shr_crc_16btable[256]; 293 294 /* Matches _shr_crc16 above */ 295 296 unsigned short 297 _shr_crc16b(int crc, unsigned char *data, int nbits) 298 { 299 int i; 300 int j; 301 unsigned int accum; 302 unsigned int poly = 0xa001; 303 int last_nbits; 304 305 if (!_shr_crc16b_table_inited) { 306 for (i = 0; i < 256; i++) { 307 accum = i; 308 309 for (j = 0; j < 8; j++) { 310 accum = (accum & 1) ? (accum >> 1 ^ poly) : (accum >> 1); 311 } 312 _shr_crc_16btable[i] = accum; 313 } 314 _shr_crc16b_table_inited = 1; 315 } 316 317 for (i = 0; i < (nbits / 8); i++) { 318 crc = (crc >> 8) ^ _shr_crc_16btable[((data[i] & 0x000000FF) << 0) ^ 319 (crc & 0x000000FF)]; 320 } 321 322 last_nbits = nbits % 8; 323 if (last_nbits) { 324 accum = (crc & ((1 << last_nbits) - 1)) ^ 325 (data[i] & ((1 << last_nbits) - 1)); 326 for (j = 0; j < last_nbits; j++) { 327 accum = (accum & 1) ? (accum >> 1 ^ poly) : (accum >> 1); 328 } 329 crc = (crc >> last_nbits) ^ accum; 330 } 331 332 return crc; 333 } 334 335 /* Matches Draco 1.5 CRC16 key76 */ 336 337 unsigned short 338 _shr_crc16bd15(int crc, unsigned char *data, int nbits) 339 { 340 int i; 341 int j; 342 unsigned int accum; 343 unsigned int poly = 0xa001; 344 int last_nbits; 345 346 if (!_shr_crc16b_table_inited) { 347 for (i = 0; i < 256; i++) { 348 accum = i; 349 350 for (j = 0; j < 8; j++) { 351 accum = (accum & 1) ? (accum >> 1 ^ poly) : (accum >> 1); 352 } 353 _shr_crc_16btable[i] = accum; 354 } 355 _shr_crc16b_table_inited = 1; 356 } 357 358 for (i = 0; i < (nbits / 8); i++) { 359 crc = (crc >> 8) ^ ((data[i] & 0x000000FF) << 8) ^ 360 _shr_crc_16btable[crc & 0x000000FF]; 361 } 362 363 last_nbits = nbits % 8; 364 if (last_nbits) { 365 accum = crc & ((1 << last_nbits) - 1); 366 for (j = 0; j < last_nbits; j++) { 367 accum = (accum & 1) ? (accum >> 1 ^ poly) : (accum >> 1); 368 } 369 crc = (crc >> last_nbits) ^ accum ^ 370 ((data[i] & ((1 << last_nbits) - 1)) << (16 - last_nbits)); 371 } 372 373 return crc; 374 } 375 376 uint16 377 _shr_crc16_draco_array(uint32 *hash_words, int n) 378 { 379 uint8 data[30]; 380 int i; 381 uint16 crc; 382 383 sal_memset(data, 0, 30); 384 385 for (i = 0; i < n; i++) { 386 data[i] = (hash_words[i/4] >> ((i % 4) * 8)) & 0xff; 387 } 388 389 crc = _shr_crc16(0, data, n); 390 crc = _shr_bit_rev16(crc); 391 392 return crc; 393 } 394 395 /* CRC16 CCITT: Polynomial x^16 + x^12 + x^5 + 1 */ 396 397 static int _shr_crc16_ccitt_table_inited; 398 static uint16 _shr_crc16_ccitt_table[256]; 399 400 uint16 401 _shr_crc16_ccitt(int crc, unsigned char *data, int len) 402 { 403 int i; 404 int j; 405 uint32 accum; 406 uint32 poly = 0x8408; 407 408 if (!_shr_crc16_ccitt_table_inited) { 409 for (i = 0; i < 256; i++) { 410 accum = i; 411 412 for (j = 0; j < 8; j++) { 413 accum = (accum & 1) ? (accum >> 1 ^ poly) : (accum >> 1); 414 } 415 _shr_crc16_ccitt_table[i] = accum; 416 } 417 _shr_crc16_ccitt_table_inited = 1; 418 } 419 420 for (i = 0; i < len; i++) { 421 crc = (crc >> 8) ^ 422 _shr_crc16_ccitt_table[((data[i] & 0x000000FF) << 0) ^ 423 (crc & 0x000000FF)]; 424 } 425 426 return crc; 427 } 428 429 uint16 430 _shr_crc16_ccitt_array(uint32 *hash_words, int n) 431 { 432 uint8 data[30]; 433 int i; 434 uint16 crc; 435 436 sal_memset(data, 0, 30); 437 438 for (i = 0; i < n; i++) { 439 data[i] = (hash_words[i/4] >> ((i % 4) * 8)) & 0xff; 440 } 441 442 crc = _shr_crc16_ccitt(0, data, n); 443 crc = _shr_bit_rev16(crc); 444 return crc; 445 } 446 447 static int _shr_crc32_cast_table_inited; 448 static uint32 _shr_crc32_cast_table[256]; 449 450 /* 451 * The following function implements polynomial: 452 * x^32 + x^28 + x^27 + x^26 + x^25 + x^23 + x^22 + x^20 + 453 * x^19 + x^18 + x^14 + x^13 + x^11 + x^10 + x^9 + x^8 + x^6 + 1 454 */ 455 uint32 456 _shr_crc32_castagnoli(unsigned int crc, unsigned char *data, int len) 457 { 458 int i; 459 460 if (!_shr_crc32_cast_table_inited) { 461 int j; 462 unsigned int accum; 463 464 for (i = 0; i < 256; i++) { 465 accum = i; 466 467 for (j = 0; j < 8; j++) { 468 if (accum & 1) { 469 accum = accum >> 1 ^ 0x82F63B78UL; 470 } else { 471 accum = accum >> 1; 472 } 473 } 474 475 _shr_crc32_cast_table[i] = _shr_swap32(accum); 476 } 477 478 _shr_crc32_cast_table_inited = 1; 479 } 480 481 for (i = 0; i < len; i++) { 482 crc = crc << 8 ^ _shr_crc32_cast_table[crc >> 24 ^ data[i]]; 483 } 484 485 return crc; 486 } 487 488 uint32 489 _shr_crc32_castagnoli_array(uint32 *hash_words, int n) 490 { 491 uint8 data[30]; 492 int i; 493 uint32 crc; 494 495 sal_memset(data, 0, 30); 496 497 for (i = 0; i < n; i++) { 498 data[i] = (hash_words[i/4] >> ((i % 4) * 8)) & 0xff; 499 } 500 501 crc = _shr_crc32_castagnoli(0, data, n); 502 crc = _shr_bit_rev_by_byte_word32(crc); 503 return crc; 504 } 505 506 static int _shr_crc32_ethernet_table_inited; 507 static uint32 _shr_crc32_ethernet_table[256]; 508 509 /* 510 * The following function implements polynomial: 511 * x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + 512 * x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 513 */ 514 uint32 515 _shr_crc32_ethernet(unsigned int crc, unsigned char *data, int len) 516 { 517 int i; 518 519 if (!_shr_crc32_ethernet_table_inited) { 520 int j; 521 unsigned int accum; 522 523 for (i = 0; i < 256; i++) { 524 accum = i; 525 526 for (j = 0; j < 8; j++) { 527 if (accum & 1) { 528 accum = accum >> 1 ^ 0xEDB88320UL; 529 } else { 530 accum = accum >> 1; 531 } 532 } 533 534 _shr_crc32_ethernet_table[i] = _shr_swap32(accum); 535 } 536 537 _shr_crc32_ethernet_table_inited = 1; 538 } 539 540 for (i = 0; i < len; i++) { 541 crc = crc << 8 ^ _shr_crc32_ethernet_table[crc >> 24 ^ data[i]]; 542 } 543 544 return crc; 545 } 546 547 uint32 548 _shr_crc32_ethernet_array(uint32 *hash_words, int n) 549 { 550 uint8 data[30]; 551 int i; 552 uint32 crc; 553 554 sal_memset(data, 0, 30); 555 556 for (i = 0; i < n; i++) { 557 data[i] = (hash_words[i/4] >> ((i % 4) * 8)) & 0xff; 558 } 559 560 crc = _shr_crc32_ethernet(0, data, n); 561 crc = _shr_bit_rev_by_byte_word32(crc); 562 return crc; 563 } 564 565 static int _shr_crc32_koopman_table_inited; 566 static uint32 _shr_crc32_koopman_table[256]; 567 568 /* 569 * The following function implements polynomial: 570 * x^32 + x^30 + x^29 + x^28 + x^26 + x^20 + x^19 + x^17 + 571 * x^16 + x^15 + x^11 + x^10 + x^7 + x^6 + x^4 + x^2 + x + 1 572 */ 573 uint32 574 _shr_crc32_koopman(unsigned int crc, unsigned char *data, int len) 575 { 576 int i; 577 578 if (!_shr_crc32_koopman_table_inited) { 579 int j; 580 unsigned int accum; 581 582 for (i = 0; i < 256; i++) { 583 accum = i; 584 585 for (j = 0; j < 8; j++) { 586 if (accum & 1) { 587 accum = accum >> 1 ^ 0xEB31D82EUL; 588 } else { 589 accum = accum >> 1; 590 } 591 } 592 593 _shr_crc32_koopman_table[i] = _shr_swap32(accum); 594 } 595 596 _shr_crc32_koopman_table_inited = 1; 597 } 598 599 for (i = 0; i < len; i++) { 600 crc = crc << 8 ^ _shr_crc32_koopman_table[crc >> 24 ^ data[i]]; 601 } 602 603 return crc; 604 } 605 606 uint32 607 _shr_crc32_koopman_array(uint32 *hash_words, int n) 608 { 609 uint8 data[30]; 610 int i; 611 uint32 crc; 612 613 sal_memset(data, 0, 30); 614 615 for (i = 0; i < n; i++) { 616 data[i] = (hash_words[i/4] >> ((i % 4) * 8)) & 0xff; 617 } 618 619 crc = _shr_crc32_koopman(0, data, n); 620 crc = _shr_bit_rev_by_byte_word32(crc); 621 return crc; 622 } 623 624 /* 625 * Function: 626 * _shr_sort 627 * Purpose: 628 * Simple general purpose Shell sort with decent performance O(N log N) 629 */ 630 631 #define A(i) ((void *) &((char *)(base))[(i) * (size)]) 632 633 void 634 _shr_sort(void *base, int count, int size, int (*compar)(void *, void *)) 635 { 636 int h = 1, i, j; 637 char tmp[256]; 638 639 assert(size < (int)sizeof(tmp)); 640 641 while (h * 3 + 1 < count) { 642 h = 3 * h + 1; 643 } 644 645 while (h > 0) { 646 for (i = h - 1; i < count; i++) { 647 sal_memcpy(tmp, A(i), size); 648 649 for (j = i; j >= h && (*compar)(A(j - h), tmp) > 0; j -= h) { 650 sal_memcpy(A(j), A(j - h), size); 651 } 652 653 sal_memcpy(A(j), tmp, size); 654 } 655 656 h /= 3; 657 } 658 } 659 660 /* 661 * Function: 662 * _shr_bsearch 663 * Purpose: 664 * Simple general purpose binary search in a (low to high) sorted array. 665 * Returns: 666 * (negative insertion index) or positive exact match index. 667 * 668 * Note that the negative insertion index is one greater than the 669 * actual insertion index to allow for an indication of the 670 * insertion index at the beginning of the array (index 0). 671 */ 672 int 673 _shr_bsearch(void *base, int count, int size, 674 void *target, int (*compar)(void *, void *)) 675 { 676 int start = 0; 677 int end = count - 1; 678 int midpoint; 679 int compare_result; 680 681 /* Keep going as long as interval of possible matches not empty. */ 682 while (end >= start) { 683 midpoint = (end + start) / 2; 684 compare_result = (*compar)(A(midpoint), target); 685 if (0 == compare_result) { 686 return midpoint; 687 } 688 if (compare_result < 0) { 689 start = midpoint + 1; 690 } else if (compare_result > 0) { 691 end = midpoint - 1; 692 } 693 } 694 695 return (-1) * (start + 1); 696 } 697 698 #undef A 699 700 /* 701 * _shr_format_integer 702 * 703 * Format an integer as a string of ASCII digits. 704 * Used for debugging printf's in the driver. 705 */ 706 707 void 708 _shr_format_integer(char *buf, unsigned int n, int min_digits, int base) 709 { 710 static char *digit_char = "0123456789abcdef"; 711 unsigned int tmp; 712 int digit, needed_digits = 0; 713 714 for (tmp = n, needed_digits = 0; tmp; needed_digits++) { 715 tmp /= base; 716 } 717 718 if (needed_digits > min_digits) 719 min_digits = needed_digits; 720 721 buf[min_digits] = 0; 722 723 for (digit = min_digits - 1; digit >= 0; digit--) { 724 buf[digit] = digit_char[n % base]; 725 n /= base; 726 } 727 } 728 729 /* 730 * _shr_format_long_integer 731 * 732 * Format an arbitrary precision long integer. 733 * 734 * If the value is less than 10, prints one decimal digit; 735 * otherwise output is in hex format with 0x prefix. 736 * 737 * val[0] is the least significant word. 738 * nval is the number of bytes in the value. 739 */ 740 741 void 742 _shr_format_long_integer(char *buf, unsigned int *val, int nval) 743 { 744 int i = BYTES2WORDS(nval) - 1; 745 746 /* 747 Don't actually skip leading 0's, as this makes packet buffers 748 and other buffer memories really hard to read and to determine 749 what the contents are. 750 */ 751 #if 0 752 for (i = BYTES2WORDS(nval) - 1; i > 0; i--) { /* Skip leading zeroes */ 753 if (val[i]) { 754 break; 755 } 756 } 757 #endif /* 0 */ 758 759 if (i == 0 && val[i] < 10) { /* Only a single word < 10 */ 760 buf[0] = '0' + val[i]; 761 buf[1] = 0; 762 } else { 763 buf[0] = '0'; /* Print first word */ 764 buf[1] = 'x'; 765 766 /* 767 Don't use the previous value of 1 min digit for multiple 768 integer values, as that makes a long integer of all zeroes 769 print as just '0', which makes memory contents hard to read. 770 Only use mindigit of 1 if only one integer to print 771 */ 772 if (i == 0) { 773 _shr_format_integer(buf + 2, val[i], 1, 16); 774 } 775 else 776 { 777 if ((nval % 4) == 0) { 778 _shr_format_integer(buf + 2, val[i], 8, 16); 779 } 780 else 781 { 782 _shr_format_integer(buf + 2, val[i], (2 * (nval % 4)), 16); 783 } 784 } 785 786 while (--i >= 0) { /* Print rest of words, if any */ 787 while (*buf) { 788 buf++; 789 } 790 791 _shr_format_integer(buf, val[i], 8, 16); 792 } 793 } 794 } 795 796 /* 797 * _shr_format_uint64_hexa_string 798 * 799 * Converts uint64 to hexa string 800 */ 801 void 802 _shr_format_uint64_hexa_string( uint64 value, char* uint64_hexa_string) 803 { 804 if(COMPILER_64_HI(value)) { 805 sal_sprintf(uint64_hexa_string, "0x%x", COMPILER_64_HI(value)); 806 sal_sprintf(uint64_hexa_string + sal_strlen(uint64_hexa_string), "%08x", COMPILER_64_LO(value)); 807 } else { 808 sal_sprintf(uint64_hexa_string, "0x%x", COMPILER_64_LO(value)); 809 } 810 } 811 812 813 814 815 /* 816 * _shr_ctoi 817 * 818 * Converts a C-style constant integer to unsigned int 819 */ 820 821 unsigned int 822 _shr_ctoi(const char *s) 823 { 824 unsigned int n, neg, base = 10; 825 826 s += (neg = (*s == '-')); 827 828 if (*s == '0') { 829 s++; 830 831 if (*s == 'x' || *s == 'X') { 832 base = 16; 833 s++; 834 } else if (*s == 'b' || *s == 'B') { 835 base = 2; 836 s++; 837 } else { 838 base = 8; 839 } 840 } 841 842 for (n = 0; ((*s >= 'a' && *s <= 'z' && base > 10) || 843 (*s >= 'A' && *s <= 'Z' && base > 10) || 844 (*s >= '0' && *s <= '9')); s++) { 845 n = n * base + 846 (*s >= 'a' ? *s - 'a' + 10 : 847 *s >= 'A' ? *s - 'A' + 10 : 848 *s - '0'); 849 } 850 851 return (neg ? -n : n); 852 } 853 854 /* 855 * _shr_ctoa 856 * 857 * Converts a C-style constant string to an address 858 */ 859 860 sal_vaddr_t 861 _shr_ctoa(const char *s) 862 { 863 unsigned int base = 10; 864 sal_vaddr_t n; 865 866 if (*s == '0') { 867 s++; 868 869 if (*s == 'x' || *s == 'X') { 870 base = 16; 871 s++; 872 } else if (*s == 'b' || *s == 'B') { 873 base = 2; 874 s++; 875 } else { 876 base = 8; 877 } 878 } 879 880 for (n = 0; ((*s >= 'a' && *s <= 'z' && base > 10) || 881 (*s >= 'A' && *s <= 'Z' && base > 10) || 882 (*s >= '0' && *s <= '9')); s++) { 883 n = n * base + 884 (*s >= 'a' ? *s - 'a' + 10 : 885 *s >= 'A' ? *s - 'A' + 10 : 886 *s - '0'); 887 } 888 889 return (n); 890 } 891 892 /* 893 * Functions to get around the lack of floating point support 894 * in Linux kernel mode. 895 */ 896 897 /* 898 * Function: 899 * _shr_div_exp10 900 * Purpose: 901 * Do uint32 division while preserving precision and 902 * avoiding overflow. 903 * Parameters: 904 * d1 - dividend 905 * d2 - divisor 906 * exp10 - factor of 10 by which to multiply the quotient 907 * Returns: 908 * Result of division. 909 * Notes: 910 * Example: 911 * 5000 * 100000000 / 12345 912 * => d1 = 5000, d2 = 12345, exp10 = 8 913 */ 914 int 915 _shr_div_exp10(int d1, int d2, int exp10) 916 { 917 int rv; 918 int e; 919 int sign = 1; 920 921 if (d2 < 0) { 922 sign = -1; 923 } 924 925 while (exp10 && d1 < (0x7FFFFFFF / 10)) { 926 d1 = d1 * 10; 927 exp10--; 928 } 929 e = 1; 930 while (exp10) { 931 e *= 10; 932 exp10--; 933 } 934 rv = (d1 / d2) * e; 935 if (e > 1) { 936 rv += ((d1 % d2) * e) / (d2 * sign); 937 } 938 return rv; 939 } 940 941 /* 942 * Function: 943 * _shr_atof_exp10 944 * Purpose: 945 * Parse floating point input string and transform the result 946 * into a 32-bit integer, optionally multiplying with an 947 * exponent of 10. 948 * Parameters: 949 * s - string to parse 950 * Returns: 951 * Binary value of input string. 952 * Notes: 953 * This is a helper function to transform floating point input 954 * into an integer value without loosing any information. 955 * 956 * Examples: 957 * _shr_atof_exp10("1.33", 6) => 1.33 * 10^6 => 1330000 958 * _shr_atof_exp10("0.1234", 3) => 0.1234 * 10^3 => 123 959 */ 960 961 int 962 _shr_atof_exp10(const char *s, int exp10) 963 { 964 int rv = 0; 965 int dec_pt = 0; 966 int sign = 10; 967 968 if (exp10 > 9 || exp10 < 0) { 969 return 0; 970 } 971 972 exp10++; 973 974 if (*s == '-') { 975 sign = -10; 976 s++; 977 } 978 979 while (*s && exp10) { 980 if (*s >= '0' && *s <= '9') { 981 if (exp10) { 982 rv *= 10; 983 } 984 rv += *s - '0'; 985 if (dec_pt && exp10) { 986 exp10--; 987 } 988 } else if (*s == '.' && !dec_pt) { 989 dec_pt = 1; 990 } else { 991 break; 992 } 993 s++; 994 } 995 while (exp10-- > 0) { 996 rv *= 10; 997 } 998 999 return (rv + 5) / sign; 1000 } 1001 1002 /* 1003 * Function: 1004 * _shr_div32r 1005 * Purpose: 1006 * Do 32 bit integer division with rounding. 1007 * Parameters: 1008 * d1 - dividend 1009 * d2 - divisor 1010 * Returns: 1011 * Result of division. 1012 */ 1013 1014 uint32 1015 _shr_div32r(uint32 d1, uint32 d2) 1016 { 1017 uint32 rv; 1018 1019 rv = d1 / d2; 1020 if ((d1 % d2) >= (d2 / 2)) { 1021 rv += 1; 1022 } 1023 return rv; 1024 } 1025 1026 /* 1027 * Function: 1028 * _shr_scale_uint64 1029 * Purpose: 1030 * Transform 64 bit integer into a 32 bit integer 1031 * and a prefix multiplier (kilo, mega, giga etc.) 1032 * Parameters: 1033 * d64 - 64 bit integer to scale 1034 * base - value of 1k (must be 1000 or 1024) 1035 * prec - precision by which result is multiplied 1036 * d32 - pointer to 32 bit integer (OUT) 1037 * Returns: 1038 * Prefix multiplier string ("", "K", "M", "G", "T"). 1039 * Notes: 1040 * This is helper function for displaying 64 bit 1041 * integers without using floating point or 64 bit 1042 * mul/div/mod. 1043 * 1044 * Example: 1045 * We want to display 20*10^12 (0x000012309ce54000) 1046 * as 20.00 T (tera): 1047 * 1048 * d64 is 0x000012309ce54000 1049 * base is 1000 (i.e. 1k = 1000) 1050 * precision is 100 (2 decimals) 1051 * 1052 * s = _shr_scale_uint64(d64, 1000, 100, &d32); 1053 * printf("%d.%02d %s", d32 / 100, d32 % 100, s); 1054 */ 1055 1056 char * 1057 _shr_scale_uint64(uint64 d64, int base, int prec, uint32 *d32) 1058 { 1059 uint32 value; 1060 uint64 value64; 1061 int t, e; 1062 1063 *d32 = 0; 1064 1065 switch (base) { 1066 case 1000: 1067 case 1024: 1068 break; 1069 default: 1070 return 0; 1071 } 1072 1073 switch (prec) { 1074 case 1: 1075 case 10: 1076 case 100: 1077 case 1000: 1078 break; 1079 default: 1080 return 0; 1081 } 1082 1083 COMPILER_64_SET(value64, COMPILER_64_HI(d64), COMPILER_64_LO(d64)); 1084 1085 e = 0; 1086 while (COMPILER_64_HI(value64)) { 1087 /* Shift down to 32 bits */ 1088 t = 0; 1089 while (COMPILER_64_HI(value64)) { 1090 COMPILER_64_SHR(value64, 1); 1091 t++; 1092 } 1093 /* Perform 32 bit division with rounding */ 1094 value = _shr_div32r(COMPILER_64_LO(value64), base); 1095 /* Shift back - precision is still adequate */ 1096 COMPILER_64_SET(value64, 0, value); 1097 COMPILER_64_SHL(value64, t); 1098 e++; 1099 } 1100 value = COMPILER_64_LO(value64); 1101 1102 t = 1; 1103 while ((value / t) > (uint32)base) { 1104 t *= base; 1105 e++; 1106 } 1107 1108 if (e > 0) { 1109 /* 1110 * COVERITY 1111 * As per switch statement on line 955, The function proceeds 1112 * only if value of prec is 1,10,100,1000 only for rest of the 1113 * values function returns so the stated condition will not occur. 1114 */ 1115 /* coverity[divide_by_zero : FALSE] */ 1116 *d32 = _shr_div32r(value, t / prec); 1117 if (e == 1) { 1118 return (base == 1000) ? "k" : "K"; 1119 } 1120 if (e == 2) { 1121 return "M"; 1122 } 1123 if (e == 3) { 1124 return "G"; 1125 } 1126 return "T"; 1127 } 1128 *d32 = prec * value; 1129 return ""; 1130 } 1131 1132 /* 1133 * Function: 1134 * _shr_ip6_mask_create 1135 * Purpose: 1136 * Create IPv6 network address from prefix length 1137 * Parameters: 1138 * ip6 - (OUT) IPv6 address holder 1139 * len - the prefix/mask length 1140 * Returns: 1141 * none 1142 */ 1143 1144 int 1145 _shr_ip6_mask_create(uint8 *ip6, int len) 1146 { 1147 int num_bytes, bits_left; 1148 int i; 1149 1150 sal_memset(ip6, 0, _SHR_L3_IP6_ADDRLEN); 1151 if (len == 0) { 1152 return _SHR_E_PARAM; 1153 } 1154 1155 if (len > _SHR_L3_IP6_MAX_NETLEN) { 1156 len = _SHR_L3_IP6_MAX_NETLEN; 1157 } 1158 1159 num_bytes = len / 8; 1160 bits_left = len % 8; 1161 1162 for (i = 0; i < num_bytes; i++) { 1163 ip6[i] = 0xff; 1164 } 1165 1166 if (bits_left) { 1167 ip6[i] = (0xff << (8 - bits_left)); 1168 } 1169 1170 return _SHR_E_NONE; 1171 } 1172 1173 1174 /* 1175 * Function: 1176 * _shr_ip6_mask_length 1177 * Purpose: 1178 * Return the mask length from IPv6 network address 1179 * Parameters: 1180 * mask - IPv6 address 1181 * Returns: 1182 * The prefix/mask length 1183 */ 1184 1185 int 1186 _shr_ip6_mask_length(uint8 *mask) 1187 { 1188 int masklen, i, j; 1189 uint8 temp; 1190 1191 /* Convert netmask to number of bits */ 1192 masklen = 0; 1193 1194 for (i = 0; i < _SHR_L3_IP6_ADDRLEN; i++) { 1195 temp = mask[i]; 1196 for (j = 0; j < 8; j++) { 1197 if (temp & 0x80) { 1198 masklen++; 1199 temp = temp << 1; 1200 } else { 1201 break; 1202 } 1203 } 1204 } 1205 return masklen; 1206 } 1207 1208 /* 1209 * Function 1210 * _shr_ip6_addr_compare 1211 * Purpose 1212 * Compare IPv6 address from LSB to MSB 1213 * Parameters 1214 * addr1 - (IN) IPv6 address 1215 * addr2 - (IN) IPv6 address 1216 * Returns 1217 * Compare result 1218 */ 1219 int 1220 _shr_ip6_addr_compare(uint8 *addr1, uint8 *addr2) 1221 { 1222 int i = 0; 1223 for (i = _SHR_L3_IP6_ADDRLEN - 1; i >= 0; i--) { 1224 if (addr1[i] != addr2[i]) { 1225 return -1; 1226 } 1227 } 1228 1229 return 0; 1230 1231 } 1232 1233 /* 1234 * Function: 1235 * _shr_ip_mask_create 1236 * Purpose: 1237 * Create IPv4 network address from prefix length 1238 * Parameters: 1239 * len - the prefix/mask length 1240 * Returns: 1241 * The IPv4 mask 1242 */ 1243 uint32 1244 _shr_ip_mask_create(int len) 1245 { 1246 return ((len) ? (~((0x1 << (32 - (len))) - 1)) : 0); 1247 } 1248 1249 /* 1250 * Function: 1251 * _shr_ip_mask_length 1252 * Purpose: 1253 * Return the mask length from IPv4 network address 1254 * Parameters: 1255 * mask - The IPv4 mask as IP address 1256 * Returns: 1257 * The IPv4 mask length 1258 */ 1259 int 1260 _shr_ip_mask_length(uint32 mask) 1261 { 1262 int masklen, i; 1263 1264 /* Convert netmask to number of bits */ 1265 masklen = 0; 1266 1267 for (i = 0; i < _SHR_L3_IP_ADDRLEN * 8; i++) { 1268 if (mask & 0x80000000) { 1269 masklen++; 1270 mask = mask << 1; 1271 } else { 1272 break; 1273 } 1274 } 1275 1276 return (masklen); 1277 } 1278 1279 /* 1280 * Function: 1281 * _shr_ip_chksum 1282 * Purpose: 1283 * Calculate IP style checksum 1284 * Parameters: 1285 * - length - length of data in bytes 1286 * - data - pointer to data 1287 * Returns: 1288 * -checksum 1289 */ 1290 unsigned short 1291 _shr_ip_chksum(unsigned int length, unsigned char *data) 1292 { 1293 unsigned int chksum = 0; 1294 unsigned short w16; 1295 int i=0; 1296 1297 while (length > 1) { 1298 w16 = (((unsigned int)data[i]) << 8) + data[i+1]; 1299 chksum += w16; 1300 i+=2; 1301 length -= 2; 1302 } 1303 if (length) { 1304 w16 = (((unsigned int)data[i]) << 8) + 0; 1305 chksum += w16; 1306 } 1307 1308 while (chksum >> 16) { 1309 chksum = (chksum & 0xFFFF) + (chksum >> 16); 1310 } 1311 1312 return (~chksum); 1313 } 1314 1315 1316 /* 1317 * Function: 1318 * _shr_tolower 1319 * Purpose: 1320 * Converts uppercase char to lowercase char 1321 * Parameters: 1322 * - c - Char to convert 1323 * Returns: 1324 * Lowercase char 1325 */ 1326 #define _shr_tolower(c) ((c >= 'A' && c <= 'Z') ? (c + 37):c) 1327 1328 /* 1329 * Function: 1330 * _shr_isxdigit 1331 * Purpose: 1332 * Returns true if char is a valid hex digit 1333 * Parameters: 1334 * - c - Char to evaluate 1335 * Returns: 1336 * True if valid hex digit, else false 1337 */ 1338 int _shr_isxdigit(char c) { 1339 if ((c >= '0' && c <= '9') || 1340 (c >= 'a' && c <= 'f') || 1341 (c >= 'A' && c <= 'F')) 1342 return 1; 1343 return 0; 1344 } 1345 1346 /* 1347 * Function: 1348 * _shr_xdigit2i 1349 * Purpose: 1350 * Converts ASCII char to integer 1351 * Parameters: 1352 * - c - Char to evaluate 1353 * Returns: 1354 * Integer value of hex digit 1355 */ 1356 int _shr_xdigit2i(char c) { 1357 if (c >= '0' && c <= '9') 1358 return (int)(c - '0'); 1359 else if (c >= 'a' && c <= 'f') 1360 return (int)(c - 'a') + 10; 1361 else if (c >= 'A' && c <= 'F') 1362 return (int)(c - 'A') + 10; 1363 return 0; 1364 } 1365 1366 /* 1367 * Function: 1368 * _shr_strchr 1369 * Purpose: 1370 * Finds first occurance of char in string 1371 * Parameters: 1372 * - str - String to evaluate 1373 * - c - Char to find in string 1374 * Returns: 1375 * Pointer to first occurance of c in string, else NULL 1376 */ 1377 char *_shr_strchr(const char *str, int c) { 1378 const char *ptr = str; 1379 1380 while(*ptr != '\0') { 1381 if (*ptr == (char)c) 1382 return (char*)ptr; 1383 ptr++; 1384 } 1385 1386 return NULL; 1387 } 1388 1389 1390 /* 1391 * Function: 1392 * _shr_isint 1393 * Purpose: 1394 * Identify well-formed int 1395 * Parameters: 1396 * - s - String to evaluate 1397 * Returns: 1398 * Return true if a constant is a well-formed integer of the type 1399 * supported by parse_integer. 1400 */ 1401 1402 int 1403 _shr_isint(char *s) 1404 { 1405 int base; 1406 1407 if (s == NULL) { 1408 return 0; 1409 } 1410 1411 if (*s == '-') { 1412 s++; 1413 } 1414 1415 if (*s == '0') { 1416 if (s[1] == 'b' || s[1] == 'B') { 1417 base = 2; 1418 s += 2; 1419 } else if (s[1] == 'x' || s[1] == 'X') { 1420 base = 16; 1421 s += 2; 1422 } else 1423 base = 8; 1424 } else { 1425 base = 10; 1426 } 1427 1428 do { 1429 if (!_shr_isxdigit((unsigned) *s) || _shr_xdigit2i(*s) >= base) { 1430 return(0); 1431 } 1432 } while (*++s); 1433 1434 return(1); 1435 } 1436 1437 /* 1438 * Function: 1439 * _shr_parse_macaddr 1440 * Purpose: 1441 * Convert mac address string to six bytes of data 1442 * Parameters: 1443 * - str - MAC string to evaluate 1444 * - macaddr - Place to store the result 1445 * Returns: 1446 */ 1447 int _shr_parse_macaddr(char *str, uint8 *macaddr) 1448 { 1449 char *s; 1450 int colon = FALSE; 1451 int i, c1, c2; 1452 1453 if (_shr_strchr(str, ':')) { /* Colon format */ 1454 colon = TRUE; 1455 } else if (*str++ != '0' || _shr_tolower(*str++) != 'x') { 1456 return -1; 1457 } else { 1458 sal_memset(macaddr, 0, 6); 1459 } 1460 /* Start at end and work back */ 1461 s = str + sal_strlen(str); 1462 for (i = 5; (i >= 0) && (s >= str); i--) { 1463 c2 = (s > str && _shr_isxdigit((unsigned) s[-1])) ? _shr_xdigit2i((unsigned) *--s) : 0; 1464 c1 = (s > str && _shr_isxdigit((unsigned) s[-1])) ? _shr_xdigit2i((unsigned) *--s) : 0; 1465 macaddr[i] = c1 * 16 + c2; 1466 if (colon && (s >= str) && (':' != *--s)) 1467 break; 1468 } 1469 return(((s <= str) && (!colon || (i == 0))) ? 0 : -1); 1470 } 1471 1472 /* 1473 * Function: 1474 * _shr_parse_ipaddr 1475 * Purpose: 1476 * Convert ip address string to four bytes of data 1477 * Parameters: 1478 * - str - IP address string to evaluate 1479 * - ipaddr - Place to store the result 1480 * Returns: 1481 */ 1482 int 1483 _shr_parse_ipaddr(char *s, sal_ip_addr_t *ipaddr) 1484 { 1485 char *ts; 1486 int i, x; 1487 sal_ip_addr_t ip = 0; 1488 1489 if (strchr(s, '.')) { /* dotted notation */ 1490 for (i = 0; i < 4; i++) { 1491 x = sal_ctoi(s, &ts); 1492 if ((x > 0xff) || (x < 0)) { 1493 return(-1); 1494 } 1495 ip = (ip << 8) | x; 1496 if (*ts != '.') { /* End of string */ 1497 break; 1498 } 1499 s = ts + 1; 1500 } 1501 if (((i != 3) || (*ts != '\0'))) { 1502 return(-1); 1503 } else { 1504 *ipaddr = ip; 1505 return(0); 1506 } 1507 } else if (_shr_isint(s)){ 1508 *ipaddr = _shr_ctoi(s); 1509 return(0); 1510 } else { 1511 return(-1); 1512 } 1513 } 1514 1515 /* routines for moving uint[16|32|64] and int64 to/from network order buffers */ 1516 1517 /* 1518 * Function: 1519 * _shr_uint16_read 1520 * Purpose: 1521 * Read a 16-bit unsigned integer from a buffer in network byte order. 1522 * Parameters: 1523 * buffer - (IN) Data buffer. 1524 * Returns: 1525 * Result. 1526 * Notes: 1527 */ 1528 uint16 1529 _shr_uint16_read( 1530 uint8* buffer) 1531 { 1532 return ((((uint16)(buffer[0])) << 8) + (((uint16)(buffer[1])))); 1533 } 1534 1535 1536 /* 1537 * Function: 1538 * _shr_uint16_write 1539 * Purpose: 1540 * Write a 16-bit unsigned integer to a buffer in network byte order. 1541 * Parameters: 1542 * value - (IN) Data. 1543 * buffer - (OUT) Data buffer. 1544 * Returns: 1545 * None. 1546 * Notes: 1547 */ 1548 void 1549 _shr_uint16_write( 1550 uint8* buffer, 1551 const uint16 value) 1552 { 1553 buffer[0] = ((value >> 8) & 0xff); 1554 buffer[1] = ((value) & 0xff); 1555 } 1556 1557 1558 /* 1559 * Function: 1560 * _shr_uint32_read 1561 * Purpose: 1562 * Read a 32-bit unsigned integer from a buffer in network byte order. 1563 * Parameters: 1564 * buffer - (IN) Data buffer. 1565 * Returns: 1566 * Result. 1567 * Notes: 1568 */ 1569 uint32 1570 _shr_uint32_read( 1571 uint8* buffer) 1572 { 1573 return ((((uint32)(buffer[0])) << 24) + 1574 (((uint32)(buffer[1])) << 16) + 1575 (((uint32)(buffer[2])) << 8) + 1576 (((uint32)(buffer[3])))); 1577 } 1578 1579 1580 /* 1581 * Function: 1582 * _shr_uint32_write 1583 * Purpose: 1584 * Write a 32-bit unsigned integer to a buffer in network byte order. 1585 * Parameters: 1586 * value - (IN) Data. 1587 * buffer - (OUT) Data buffer. 1588 * Returns: 1589 * None. 1590 * Notes: 1591 */ 1592 void 1593 _shr_uint32_write( 1594 uint8* buffer, 1595 const uint32 value) 1596 { 1597 buffer[0] = ((value >> 24) & 0xff); 1598 buffer[1] = ((value >> 16) & 0xff); 1599 buffer[2] = ((value >> 8) & 0xff); 1600 buffer[3] = ((value) & 0xff); 1601 } 1602 1603 1604 /* 1605 * Function: 1606 * _shr_uint64_read 1607 * Purpose: 1608 * Read a 64-bit unsigned integer from a buffer in network byte order. 1609 * Parameters: 1610 * buffer - (IN) Data buffer. 1611 * Returns: 1612 * Result. 1613 * Notes: 1614 */ 1615 uint64 1616 _shr_uint64_read(uint8* buffer) 1617 { 1618 uint64 val64; 1619 1620 COMPILER_64_SET(val64, 1621 (buffer[0] << 24) + (buffer[1] << 16) + 1622 (buffer[2] << 8) + buffer[3], 1623 (buffer[4] << 24) + (buffer[5] << 16) + 1624 (buffer[6] << 8) + buffer[7]); 1625 return val64; 1626 } 1627 1628 1629 /* 1630 * Function: 1631 * _shr_uint64_write 1632 * Purpose: 1633 * Write a 64-bit unsigned integer to a buffer in network byte order. 1634 * Parameters: 1635 * value - (IN) Data. 1636 * buffer - (OUT) Data buffer. 1637 * Returns: 1638 * None. 1639 * Notes: 1640 */ 1641 void 1642 _shr_uint64_write( 1643 uint8* buffer, 1644 const uint64 value) 1645 { 1646 uint32 low; 1647 uint32 high; 1648 1649 COMPILER_64_TO_32_LO(low,value); 1650 COMPILER_64_TO_32_HI(high,value); 1651 1652 buffer[0] = ((high >> 24) & 0xff); 1653 buffer[1] = ((high >> 16) & 0xff); 1654 buffer[2] = ((high >> 8) & 0xff); 1655 buffer[3] = ((high) & 0xff); 1656 buffer[4] = ((low >> 24) & 0xff); 1657 buffer[5] = ((low >> 16) & 0xff); 1658 buffer[6] = ((low >> 8) & 0xff); 1659 buffer[7] = ((low) & 0xff); 1660 } 1661 1662 1663 /* 1664 * Function: 1665 * _shr_int64_read 1666 * Purpose: 1667 * Read a 64-bit signed integer from a buffer in network byte order. 1668 * Parameters: 1669 * buffer - (IN) Data buffer. 1670 * Returns: 1671 * Result. 1672 * Notes: 1673 * Casting to and from int64_t is not available on some platforms 1674 */ 1675 int64 1676 _shr_int64_read(uint8* buffer) 1677 { 1678 int64 val; 1679 int64 temp; 1680 1681 COMPILER_64_SET(temp, buffer[0] << 24, 0); 1682 val = temp; 1683 COMPILER_64_SET(temp, buffer[1] << 16, 0); 1684 COMPILER_64_ADD_64(val, temp); 1685 COMPILER_64_SET(temp, buffer[2] << 8, 0); 1686 COMPILER_64_ADD_64(val, temp); 1687 COMPILER_64_SET(temp, buffer[3], 0); 1688 COMPILER_64_ADD_64(val, temp); 1689 COMPILER_64_SET(temp, 0, buffer[4] << 24); 1690 COMPILER_64_ADD_64(val, temp); 1691 COMPILER_64_SET(temp, 0, buffer[5] << 16); 1692 COMPILER_64_ADD_64(val, temp); 1693 COMPILER_64_SET(temp, 0, buffer[6] << 8); 1694 COMPILER_64_ADD_64(val, temp); 1695 COMPILER_64_SET(temp, 0, buffer[7]); 1696 COMPILER_64_ADD_64(val, temp); 1697 1698 return val; 1699 } 1700 1701 1702 /* 1703 * Function: 1704 * _shr_int64_write 1705 * Purpose: 1706 * Write a 64-bit signed integer to a buffer in network byte order. 1707 * Parameters: 1708 * value - (IN) Data. 1709 * buffer - (OUT) Data buffer. 1710 * Returns: 1711 * None. 1712 * Notes: 1713 * Casting to and from int64_t is not available on some platforms 1714 */ 1715 void 1716 _shr_int64_write( 1717 uint8* buffer, 1718 const int64 value) 1719 { 1720 buffer[0] = (COMPILER_64_HI(value) >> 24) & 0xff; 1721 buffer[1] = (COMPILER_64_HI(value) >> 16) & 0xff; 1722 buffer[2] = (COMPILER_64_HI(value) >> 8) & 0xff; 1723 buffer[3] = (COMPILER_64_HI(value) & 0xff); 1724 buffer[4] = (COMPILER_64_LO(value) >> 24) & 0xff; 1725 buffer[5] = (COMPILER_64_LO(value) >> 16) & 0xff; 1726 buffer[6] = (COMPILER_64_LO(value) >> 8) & 0xff; 1727 buffer[7] = (COMPILER_64_LO(value) & 0xff); 1728 } 1729 1730 static void shr_rdpc_dispatcher(void *owner, void* p0, void* p1, void* p2, void* p3) 1731 { 1732 shr_rdpc_t *rdpc = (shr_rdpc_t *)owner; 1733 sal_usecs_t next_call = 0; 1734 1735 if (rdpc->running) { 1736 next_call = rdpc->func(&p0, &p1, &p2, &p3); 1737 } 1738 1739 if (sal_mutex_take(rdpc->call_count_lock, RDPC_MUTEX_TIMEOUT) != 0) { 1740 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META("RDPC dispatch failed to get mutex\n"))); 1741 } else { 1742 if (next_call && rdpc->running && rdpc->run_count == 1) { 1743 int rv = sal_dpc_time(next_call, &shr_rdpc_dispatcher, (void*)rdpc, p0, p1, p2, p3); 1744 if (rv) { 1745 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META("RDPC scheduling of DPC failed\n"))); 1746 rdpc->run_count--; 1747 } 1748 } else { 1749 if (rdpc->run_count <= 0) { 1750 /* run count was incremented every time this rdpc was started, and decremented 1751 when it did not reschedule itself. If we're here, it should be positive */ 1752 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META("RDPC run count invalid\n"))); 1753 } else { 1754 /* Either the RDPC was stopped, or it was started multiple times (possibly racing a stop) */ 1755 /* in the latter case, let it drain so only one DPC is scheduled for it */ 1756 rdpc->run_count--; 1757 } 1758 } 1759 sal_mutex_give(rdpc->call_count_lock); 1760 } 1761 } 1762 1763 /* 1764 * Function: 1765 * shr_rdpc_callback_create 1766 * Purpose: 1767 * Creates a new RDPC callback in the provided structure. RDPC will not be called until started. 1768 * Parameters: 1769 * rdpc - (IN/OUT) Pointer to RDPC structure to be initialized/created 1770 * func - (IN) The callback function 1771 * Returns: 1772 * Error code or SOC_E_NONE 1773 * Notes: 1774 */ 1775 int shr_rdpc_callback_create(shr_rdpc_t *rdpc, shr_rdpc_fn_t func) 1776 { 1777 rdpc->func = func; 1778 rdpc->call_count_lock = sal_mutex_create("rdpc"); 1779 rdpc->run_count = 0; 1780 rdpc->running = 0; 1781 1782 return rdpc->call_count_lock ? SOC_E_NONE : SOC_E_MEMORY; 1783 } 1784 1785 /* 1786 * Function: 1787 * shr_rdpc_callback_created 1788 * Purpose: 1789 * Indicates whether a shr_rdpc_t structures with static/global allocation has been created 1790 * Parameters: 1791 * rdpc - (IN/OUT) Pointer to RDPC structure to be initialized/created 1792 * Returns: 1793 * SOC_E_INIT (callback is null) or SOC_E_NONE (callback has been created) 1794 * Notes: 1795 */ 1796 int shr_rdpc_callback_created(shr_rdpc_t *rdpc) 1797 { 1798 return (rdpc->call_count_lock) ? SOC_E_NONE : SOC_E_INIT; 1799 } 1800 1801 /* 1802 * Function: 1803 * shr_rdpc_callback_start 1804 * Purpose: 1805 * Runs the callback after the specified interval. The value returned from 1806 * the callback will be used as the interval before the subsequent call. 1807 * If callback is already scheduled to run, it will execute at the earlier time. 1808 * Parameters: 1809 * rdpc - (IN) Pointer to RDPC structure 1810 * first_interval - time in usecs before the callback should be called 1811 * p0...p3 - callback will get pointers to these void* parameters 1812 * Returns: 1813 * Error code or SOC_E_NONE 1814 * Notes: 1815 */ 1816 int shr_rdpc_callback_start(shr_rdpc_t *rdpc, sal_usecs_t first_interval, 1817 void* p0, void* p1, void* p2, void* p3) 1818 { 1819 int rv = SOC_E_NONE; 1820 1821 if (sal_mutex_take(rdpc->call_count_lock, RDPC_MUTEX_TIMEOUT) != 0) { 1822 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META("RDPC dispatch failed to get mutex\n"))); 1823 return SOC_E_INTERNAL; 1824 } 1825 1826 rdpc->running = 1; 1827 rdpc->run_count++; 1828 rv = sal_dpc_time(first_interval, &shr_rdpc_dispatcher, (void*)rdpc, (void*)p0, (void*)p1, (void*)p2, (void*)p3); 1829 1830 sal_mutex_give(rdpc->call_count_lock); 1831 1832 return rv; 1833 } 1834 1835 /* 1836 * Function: 1837 * shr_rdpc_callback_stop 1838 * Purpose: 1839 * Stops further calls of the callback. 1840 * Parameters: 1841 * rdpc - (IN) Pointer to RDPC structure 1842 * Returns: 1843 * Error code or SOC_E_NONE 1844 * Notes: 1845 */ 1846 int shr_rdpc_callback_stop(shr_rdpc_t *rdpc) 1847 { 1848 int rv = SOC_E_NONE; 1849 1850 if (sal_mutex_take(rdpc->call_count_lock, RDPC_MUTEX_TIMEOUT) != 0) { 1851 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META("RDPC dispatch failed to get mutex\n"))); 1852 return SOC_E_INTERNAL; 1853 } 1854 rdpc->running = 0; 1855 sal_mutex_give(rdpc->call_count_lock); 1856 return rv; 1857 } 1858 1859 /* 1860 * Function: 1861 * shr_rdpc_callback_finished 1862 * Purpose: 1863 * Indicates whether the callback structure is still in use after having been stopped. 1864 * Parameters: 1865 * rdpc - (IN) Pointer to RDPC structure 1866 * Returns: 1867 * SOC_E_BUSY : still in use. The callback should not be destroyed yet. 1868 * SOC_E_NONE : all activity has been completed, callback may be destroyed. 1869 * Notes: 1870 */ 1871 int shr_rdpc_callback_finished(shr_rdpc_t *rdpc) 1872 { 1873 int rv = SOC_E_NONE; 1874 1875 if (sal_mutex_take(rdpc->call_count_lock, RDPC_MUTEX_TIMEOUT) != 0) { 1876 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META("RDPC dispatch failed to get mutex\n"))); 1877 return SOC_E_INTERNAL; 1878 } 1879 if (rdpc->run_count > 0) { 1880 rv = SOC_E_BUSY; 1881 } 1882 sal_mutex_give(rdpc->call_count_lock); 1883 return rv; 1884 } 1885 /* 1886 * Function: 1887 * shr_rdpc_callback_destroy 1888 * Purpose: 1889 * Releases resources associated with the RDPC structure 1890 * Parameters: 1891 * rdpc - (IN) Pointer to RDPC structure 1892 * Returns: 1893 * SOC_E_BUSY : callback is still in use and was not destroyed 1894 * SOC_E_NONE 1895 * Notes: 1896 */ 1897 int shr_rdpc_callback_destroy(shr_rdpc_t *rdpc) 1898 { 1899 int rv = shr_rdpc_callback_finished(rdpc); 1900 if (rv == 0) { 1901 sal_mutex_destroy(rdpc->call_count_lock); 1902 } 1903 1904 return rv; 1905 }