util.c (20775B)
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 * File: util.c 8 * 9 * Purpose: 10 * 11 * Functions: 12 * _bcm_ptp_uint16_read 13 * _bcm_ptp_uint32_read 14 * _bcm_ptp_uint64_read 15 * _bcm_ptp_uint16_write 16 * _bcm_ptp_uint32_write 17 * _bcm_ptp_uint64_write 18 * _bcm_ptp_int64_read 19 * _bcm_ptp_function_precheck 20 * _bcm_ptp_clock_lookup 21 * _bcm_ptp_peer_address_convert 22 * _bcm_ptp_port_address_convert 23 * _bcm_ptp_peer_address_raw_compare 24 * _bcm_ptp_peer_address_compare 25 * _bcm_ptp_port_address_compare 26 * _bcm_ptp_addr_len 27 * _bcm_ptp_is_clockid_null 28 * _bcm_ptp_port_address_cmp 29 * _bcm_ptp_dump_hex 30 */ 31 32 #if defined(INCLUDE_PTP) 33 34 #include <shared/bsl.h> 35 36 #include <soc/defs.h> 37 #include <soc/drv.h> 38 #include <shared/bsl.h> 39 #include <sal/core/time.h> 40 #include <sal/core/dpc.h> 41 #include <shared/bsl.h> 42 #include <bcm/ptp.h> 43 #include <bcm_int/common/ptp.h> 44 #include <bcm/error.h> 45 46 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) 47 #ifdef NO_SAL_APPL 48 #include <string.h> 49 #else 50 #include <sal/appl/sal.h> 51 #endif 52 #include <include/soc/uc.h> 53 #endif /* BCM_PTP_INTERNAL_STACK_SUPPORT */ 54 #include <bcm_int/control.h> 55 56 #define PTP_UTIL_HEXDUMP_LINE_WIDTH_OCTETS (100) 57 58 59 static const bcm_ptp_clock_identity_t BCM_PTP_ALL_CLOCKS = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; 60 61 /* 62 * Function: 63 * _bcm_ptp_uint16_read 64 * Purpose: 65 * Read a 16-bit unsigned integer from a buffer in network byte order. 66 * Parameters: 67 * buffer - (IN) Data buffer. 68 * Returns: 69 * Result. 70 * Notes: 71 */ 72 uint16 73 _bcm_ptp_uint16_read( 74 uint8* buffer) 75 { 76 return ((((uint16)(buffer[0])) << 8) + (((uint16)(buffer[1])))); 77 } 78 79 /* 80 * Function: 81 * _bcm_ptp_uint32_read 82 * Purpose: 83 * Read a 32-bit unsigned integer from a buffer in network byte order. 84 * Parameters: 85 * buffer - (IN) Data buffer. 86 * Returns: 87 * Result. 88 * Notes: 89 */ 90 uint32 91 _bcm_ptp_uint32_read( 92 uint8* buffer) 93 { 94 return ((((uint32)(buffer[0])) << 24) + 95 (((uint32)(buffer[1])) << 16) + 96 (((uint32)(buffer[2])) << 8) + 97 (((uint32)(buffer[3])))); 98 } 99 100 /* 101 * Function: 102 * _bcm_ptp_uint64_read 103 * Purpose: 104 * Read a 64-bit unsigned integer from a buffer in network byte order. 105 * Parameters: 106 * buffer - (IN) Data buffer. 107 * Returns: 108 * Result. 109 * Notes: 110 */ 111 uint64 112 _bcm_ptp_uint64_read(uint8* buffer) 113 { 114 uint64 val64; 115 116 COMPILER_64_SET(val64, 117 (buffer[0] << 24) + (buffer[1] << 16) + 118 (buffer[2] << 8) + buffer[3], 119 (buffer[4] << 24) + (buffer[5] << 16) + 120 (buffer[6] << 8) + buffer[7]); 121 return val64; 122 } 123 124 /* 125 * Function: 126 * _bcm_ptp_uint16_write 127 * Purpose: 128 * Write a 16-bit unsigned integer to a buffer in network byte order. 129 * Parameters: 130 * value - (IN) Data. 131 * buffer - (OUT) Data buffer. 132 * Returns: 133 * None. 134 * Notes: 135 */ 136 void 137 _bcm_ptp_uint16_write( 138 uint8* buffer, 139 const uint16 value) 140 { 141 buffer[0] = ((value >> 8) & 0xff); 142 buffer[1] = ((value) & 0xff); 143 } 144 145 /* 146 * Function: 147 * _bcm_ptp_uint32_write 148 * Purpose: 149 * Write a 32-bit unsigned integer to a buffer in network byte order. 150 * Parameters: 151 * value - (IN) Data. 152 * buffer - (OUT) Data buffer. 153 * Returns: 154 * None. 155 * Notes: 156 */ 157 void 158 _bcm_ptp_uint32_write( 159 uint8* buffer, 160 const uint32 value) 161 { 162 buffer[0] = ((value >> 24) & 0xff); 163 buffer[1] = ((value >> 16) & 0xff); 164 buffer[2] = ((value >> 8) & 0xff); 165 buffer[3] = ((value) & 0xff); 166 } 167 168 /* 169 * Function: 170 * _bcm_ptp_uint64_write 171 * Purpose: 172 * Write a 64-bit unsigned integer to a buffer in network byte order. 173 * Parameters: 174 * value - (IN) Data. 175 * buffer - (OUT) Data buffer. 176 * Returns: 177 * None. 178 * Notes: 179 */ 180 void 181 _bcm_ptp_uint64_write( 182 uint8* buffer, 183 const uint64 value) 184 { 185 uint32 low; 186 uint32 high; 187 188 COMPILER_64_TO_32_LO(low,value); 189 COMPILER_64_TO_32_HI(high,value); 190 191 buffer[0] = ((high >> 24) & 0xff); 192 buffer[1] = ((high >> 16) & 0xff); 193 buffer[2] = ((high >> 8) & 0xff); 194 buffer[3] = ((high) & 0xff); 195 buffer[4] = ((low >> 24) & 0xff); 196 buffer[5] = ((low >> 16) & 0xff); 197 buffer[6] = ((low >> 8) & 0xff); 198 buffer[7] = ((low) & 0xff); 199 } 200 201 /* 202 * Function: 203 * _bcm_ptp_int64_write 204 * Purpose: 205 * Write a 64-bit signed integer to a buffer in network byte order. 206 * Parameters: 207 * value - (IN) Data. 208 * buffer - (OUT) Data buffer. 209 * Returns: 210 * None. 211 * Notes: 212 * Casting to and from int64_t is not available on some platforms 213 */ 214 void 215 _bcm_ptp_int64_write( 216 uint8* buffer, 217 const int64 value) 218 { 219 buffer[0] = (COMPILER_64_HI(value) >> 24) & 0xff; 220 buffer[1] = (COMPILER_64_HI(value) >> 16) & 0xff; 221 buffer[2] = (COMPILER_64_HI(value) >> 8) & 0xff; 222 buffer[3] = (COMPILER_64_HI(value) & 0xff); 223 buffer[4] = (COMPILER_64_LO(value) >> 24) & 0xff; 224 buffer[5] = (COMPILER_64_LO(value) >> 16) & 0xff; 225 buffer[6] = (COMPILER_64_LO(value) >> 8) & 0xff; 226 buffer[7] = (COMPILER_64_LO(value) & 0xff); 227 } 228 229 230 /* 231 * Function: 232 * _bcm_ptp_int64_read 233 * Purpose: 234 * Read a 64-bit signed integer from a buffer in network byte order. 235 * Parameters: 236 * buffer - (IN) Data buffer. 237 * Returns: 238 * Result. 239 * Notes: 240 * Casting to and from int64_t is not available on some platforms 241 */ 242 int64 243 _bcm_ptp_int64_read(uint8* buffer) 244 { 245 int64 val; 246 int64 temp; 247 248 COMPILER_64_SET(temp, buffer[0] << 24, 0); 249 val = temp; 250 COMPILER_64_SET(temp, buffer[1] << 16, 0); 251 COMPILER_64_ADD_64(val, temp); 252 COMPILER_64_SET(temp, buffer[2] << 8, 0); 253 COMPILER_64_ADD_64(val, temp); 254 COMPILER_64_SET(temp, buffer[3], 0); 255 COMPILER_64_ADD_64(val, temp); 256 COMPILER_64_SET(temp, 0, buffer[4] << 24); 257 COMPILER_64_ADD_64(val, temp); 258 COMPILER_64_SET(temp, 0, buffer[5] << 16); 259 COMPILER_64_ADD_64(val, temp); 260 COMPILER_64_SET(temp, 0, buffer[6] << 8); 261 COMPILER_64_ADD_64(val, temp); 262 COMPILER_64_SET(temp, 0, buffer[7]); 263 COMPILER_64_ADD_64(val, temp); 264 265 return val; 266 } 267 268 269 /* 270 * Function: 271 * _bcm_ptp_function_precheck 272 * Purpose: 273 * Perform basic argument and PTP module prechecks on a function. 274 * Parameters: 275 * unit - (IN) Unit number. 276 * ptp_id - (IN) PTP stack ID. 277 * clock_num - (IN) PTP clock number. 278 * clock_port - (IN) PTP clock port number. 279 * Returns: 280 * BCM_E_XXX 281 * Notes: 282 */ 283 int 284 _bcm_ptp_function_precheck( 285 int unit, 286 bcm_ptp_stack_id_t ptp_id, 287 int clock_num, 288 uint32 clock_port) 289 { 290 int rv = BCM_E_UNAVAIL; 291 292 _bcm_ptp_info_t *ptp_info_p; 293 bcm_ptp_clock_info_t ci; 294 295 if ((unit < PTP_UNIT_NUMBER_DEFAULT) || 296 (unit >= BCM_MAX_NUM_UNITS)) { 297 return BCM_E_PARAM; 298 } 299 300 if (soc_feature(unit, soc_feature_ptp)) { 301 SET_PTP_INFO; 302 303 if (ptp_info_p->memstate != PTP_MEMSTATE_INITIALIZED) { 304 return BCM_E_UNAVAIL; 305 } 306 307 /* Argument checking and error handling. */ 308 if ((ptp_id < PTP_STACK_ID_DEFAULT) || 309 (ptp_id >= PTP_MAX_STACKS_PER_UNIT) || 310 (clock_num < PTP_CLOCK_NUMBER_DEFAULT) || 311 (clock_num >= PTP_MAX_CLOCK_INSTANCES)) { 312 return BCM_E_PARAM; 313 } 314 315 if ((clock_port == PTP_IEEE1588_ALL_PORTS) || 316 (clock_port == PTP_CLOCK_PORT_NUMBER_DEFAULT)) { 317 return BCM_E_NONE; 318 } else { 319 if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_info_get(unit, ptp_id, 320 clock_num, &ci))) { 321 return rv; 322 } 323 324 if ((clock_port < PTP_CLOCK_PORT_NUMBER_DEFAULT) || 325 (clock_port > ci.num_ports)) { 326 return BCM_E_PORT; 327 } 328 329 switch (ci.type) { 330 case bcmPTPClockTypeOrdinary: 331 case bcmPTPClockTypeBoundary: 332 case bcmPTPClockTypeTransparent: 333 break; 334 default: 335 return BCM_E_PARAM; 336 } 337 } 338 339 } 340 341 return rv; 342 } 343 344 /* 345 * Function: 346 * _bcm_ptp_clock_lookup 347 * Purpose: 348 * Lookup the PTP clock number of a PTP clock for a given unit / PTP stack ID 349 * based on caller-provided clock identity. 350 * Parameters: 351 * clock_identity - (IN) PTP clock identity to lookup. 352 * unit - (IN) Unit number. 353 * ptp_id - (IN) PTP stack ID. 354 * clock_num - (OUT) PTP clock number. 355 * Returns: 356 * BCM_E_XXX 357 * Notes: 358 */ 359 int _bcm_ptp_clock_lookup( 360 const bcm_ptp_clock_identity_t clock_identity, 361 int unit, 362 bcm_ptp_stack_id_t ptp_id, 363 int *clock_num) 364 { 365 bcm_ptp_clock_info_t ci; 366 int i; 367 368 /* Affiliate "all-clocks" clockIdentity with default stack, unit, and clock number. */ 369 if (!memcmp(BCM_PTP_ALL_CLOCKS, clock_identity, sizeof(bcm_ptp_clock_identity_t))) { 370 /* this should only match if the unit/ptp_id match the defaults */ 371 if (unit == PTP_UNIT_NUMBER_DEFAULT && ptp_id == PTP_STACK_ID_DEFAULT) { 372 *clock_num = PTP_CLOCK_NUMBER_DEFAULT; 373 return BCM_E_NONE; 374 } else { 375 return BCM_E_NOT_FOUND; 376 } 377 } 378 379 if (!BCM_UNIT_VALID(unit)) { 380 return BCM_E_NOT_FOUND; 381 } 382 383 if ((unit < PTP_UNIT_NUMBER_DEFAULT) || 384 (unit >= BCM_MAX_NUM_UNITS)) 385 { 386 return BCM_E_PARAM; 387 } 388 389 for (i = PTP_CLOCK_NUMBER_DEFAULT; i < PTP_MAX_CLOCK_INSTANCES; ++i) { 390 if (BCM_FAILURE(_bcm_ptp_clock_cache_info_get(unit, ptp_id, i, &ci))) { 391 continue; 392 } 393 394 if (!memcmp(ci.clock_identity, clock_identity, sizeof(bcm_ptp_clock_identity_t))) { 395 *clock_num = i; 396 return BCM_E_NONE; 397 } 398 } 399 400 return BCM_E_NOT_FOUND; 401 } 402 403 /* Function: 404 * _bcm_ptp_peer_address_convert 405 * Purpose: 406 * Convert address from peer format to clock-port format. 407 * Parameters: 408 * peer_addr - (IN) Address (peer format). 409 * port_addr - (OUT) Address (clock-port format). 410 * Returns: 411 * BCM_E_XXX - Function status. 412 * Notes: 413 */ 414 int 415 _bcm_ptp_peer_address_convert( 416 bcm_ptp_clock_peer_address_t *peer_addr, 417 bcm_ptp_clock_port_address_t *port_addr) 418 { 419 port_addr->addr_type = peer_addr->addr_type; 420 421 memset(port_addr->address, 0, BCM_PTP_MAX_NETW_ADDR_SIZE); 422 switch (peer_addr->addr_type) { 423 case bcmPTPUDPIPv4: 424 _bcm_ptp_uint32_write(port_addr->address, peer_addr->ipv4_addr); 425 break; 426 427 case bcmPTPUDPIPv6: 428 memcpy(port_addr->address, peer_addr->ipv6_addr, PTP_IPV6_ADDR_SIZE_BYTES); 429 break; 430 431 default: 432 return BCM_E_PARAM; 433 434 } 435 436 return BCM_E_NONE; 437 } 438 439 /* 440 * Function: 441 * _bcm_ptp_port_address_convert 442 * Purpose: 443 * Convert address from clock-port format to peer format. 444 * Parameters: 445 * port_addr - (IN) Address (clock-port format). 446 * peer_addr - (OUT) Address (peer format). 447 * Returns: 448 * BCM_E_XXX - Function status. 449 * Notes: 450 */ 451 int 452 _bcm_ptp_port_address_convert( 453 bcm_ptp_clock_port_address_t *port_addr, 454 bcm_ptp_clock_peer_address_t *peer_addr) 455 { 456 peer_addr->addr_type = port_addr->addr_type; 457 458 switch (port_addr->addr_type) { 459 case bcmPTPUDPIPv4: 460 peer_addr->ipv4_addr = _bcm_ptp_uint32_read(port_addr->address); 461 break; 462 463 case bcmPTPUDPIPv6: 464 memcpy(peer_addr->ipv6_addr, port_addr->address, PTP_IPV6_ADDR_SIZE_BYTES); 465 break; 466 467 default: 468 return BCM_E_PARAM; 469 470 } 471 472 return BCM_E_NONE; 473 } 474 475 /* 476 * Function: 477 * _bcm_ptp_peer_address_raw_compare 478 * Purpose: 479 * Compare addresses. 480 * Address "A" is a peer-address type. 481 * Address "B" is a raw multi-octet buffer. 482 * Parameters: 483 * a - (IN) Address "A". 484 * b - (IN) Address "B". 485 * protocol - (IN) Address "B" network protocol. 486 * Returns: 487 * 0: Addresses do not match. 488 * 1: Addresses match. 489 * Notes: 490 */ 491 int 492 _bcm_ptp_peer_address_raw_compare( 493 const bcm_ptp_clock_peer_address_t *a, 494 uint8 *b, 495 bcm_ptp_protocol_t protocol) 496 { 497 if (a->addr_type != protocol) { 498 return 0; 499 } 500 501 switch (protocol) { 502 case bcmPTPUDPIPv4: 503 return (a->ipv4_addr == _bcm_ptp_uint32_read(b)); 504 case bcmPTPUDPIPv6: 505 return !memcmp(a->ipv6_addr, b, PTP_IPV6_ADDR_SIZE_BYTES); 506 default: 507 return 0; 508 } 509 } 510 511 /* 512 * Function: 513 * _bcm_ptp_peer_address_compare 514 * Purpose: 515 * Compare addresses. 516 * Parameters: 517 * a - (IN) Address "A". 518 * b - (IN) Address "B". 519 * Returns: 520 * 0: Addresses do not match. 521 * 1: Addresses match. 522 * Notes: 523 */ 524 int 525 _bcm_ptp_peer_address_compare( 526 const bcm_ptp_clock_peer_address_t *a, 527 const bcm_ptp_clock_peer_address_t *b) 528 { 529 if (a->addr_type != b->addr_type) { 530 return 0; 531 } 532 533 switch (a->addr_type) { 534 case bcmPTPUDPIPv4: 535 return (a->ipv4_addr == b->ipv4_addr); 536 case bcmPTPUDPIPv6: 537 return !memcmp(a->ipv6_addr, b->ipv6_addr, PTP_IPV6_ADDR_SIZE_BYTES); 538 default: 539 return 0; 540 } 541 } 542 543 /* 544 * Function: 545 * _bcm_ptp_peer_portid_compare 546 * Purpose: 547 * Compare port Identity. 548 * Parameters: 549 * a - (IN) ClockId "A". 550 * b - (IN) ClockId "B". 551 * Returns: 552 * 0: Not match. 553 * 1: Match. 554 * Notes: 555 */ 556 int 557 _bcm_ptp_peer_portid_compare( 558 const bcm_ptp_port_identity_t *a, 559 const bcm_ptp_port_identity_t *b) 560 { 561 562 /* 563 LOG_VERBOSE(BSL_LS_BCM_PTP, 564 (BSL_META_U(0, " PortId_A[%0x %0x %0x %0x %0x %0x %0x %0x : %d] PortId_B[%0x %0x %0x %0x %0x %0x %0x %0x : %d] \n"), 565 a->clock_identity[0],a->clock_identity[1],a->clock_identity[2], 566 a->clock_identity[3],a->clock_identity[4],a->clock_identity[5], 567 a->clock_identity[6],a->clock_identity[7], 568 a->port_number, 569 b->clock_identity[0],b->clock_identity[1],b->clock_identity[2], 570 b->clock_identity[3],b->clock_identity[4],b->clock_identity[5], 571 b->clock_identity[6],b->clock_identity[7], 572 b->port_number)); 573 */ 574 575 if (a->port_number != b->port_number) { 576 return 0; 577 } 578 579 return !memcmp(a->clock_identity, b->clock_identity, sizeof(bcm_ptp_clock_identity_t)); 580 } 581 582 /* 583 * Function: 584 * _bcm_ptp_port_address_compare 585 * Purpose: 586 * Compare addresses (clock-port address format). 587 * Parameters: 588 * a - (IN) Address "A". 589 * b - (IN) Address "B". 590 * Returns: 591 * 0: Addresses do not match. 592 * 1: Addresses match. 593 * Notes: 594 */ 595 int 596 _bcm_ptp_port_address_compare( 597 const bcm_ptp_clock_port_address_t *a, 598 const bcm_ptp_clock_port_address_t *b) 599 { 600 if (a->addr_type != b->addr_type) { 601 return 0; 602 } 603 604 return !memcmp(a->address, b->address, _bcm_ptp_addr_len((int)a->addr_type)); 605 } 606 607 /* 608 * Function: 609 * _bcm_ptp_addr_len 610 * Purpose: 611 * Determine address length. 612 * Parameters: 613 * addr_type - (IN) Address Type 614 * Returns: 615 * 0 : Invalid Address Type. 616 * Address Length : Valid Address Type 617 * 618 * Notes: 619 */ 620 int _bcm_ptp_addr_len(int addr_type) { 621 switch (addr_type) { 622 case bcmPTPUDPIPv4: 623 return PTP_IPV4_ADDR_SIZE_BYTES; 624 case bcmPTPUDPIPv6: 625 return PTP_IPV6_ADDR_SIZE_BYTES; 626 case bcmPTPIEEE8023: 627 return 6; 628 default: 629 return 0; 630 } 631 } 632 633 /* 634 * Function: 635 * _bcm_ptp_is_clock_id_null 636 * Purpose: 637 * Check if PTP clock identity is all zeros. 638 * Parameters: 639 * clockID - (IN) PTP Clock Identity. 640 * Returns: 641 * 0: Clock Identity is not NULL 642 * 1: Clock Identity is NULL 643 * Notes: 644 */ 645 int _bcm_ptp_is_clockid_null(bcm_ptp_clock_identity_t clockID) 646 { 647 int i; 648 for (i = 0; i < BCM_PTP_CLOCK_EUID_IEEE1588_SIZE; ++i) { 649 if (clockID[i] != 0) { 650 return 0; 651 } 652 } 653 return 1; 654 } 655 656 /* 657 * Function: 658 * _bcm_ptp_port_address_cmp 659 * Purpose: 660 * Compare addresses. 661 * Parameters: 662 * a - (IN) Address "A". 663 * b - (IN) Address "B". 664 * Returns: 665 * 0: Addresses match. 666 * Nonzero: Addresses do not match. 667 * Notes: 668 */ 669 int _bcm_ptp_port_address_cmp(bcm_ptp_clock_port_address_t *a, bcm_ptp_clock_port_address_t *b) 670 { 671 if (a->addr_type > b->addr_type) { 672 return 1; 673 } 674 if (a->addr_type < b->addr_type) { 675 return -1; 676 } 677 return memcmp(a->address, b->address, _bcm_ptp_addr_len(a->addr_type)); 678 } 679 680 /* 681 * Function: 682 * _bcm_ptp_dump_hex 683 * Purpose: 684 * Print hexadecimal buffer. 685 * Parameters: 686 * buf - (IN) buffer to be printed 687 * len - (IN) message length 688 * indent - (IN) number of spaces to indent 689 * Returns: 690 * none 691 * Notes: 692 */ 693 void _bcm_ptp_dump_hex(uint8 *buf, int len, int indent) 694 { 695 char line[PTP_UTIL_HEXDUMP_LINE_WIDTH_OCTETS]; 696 int i,j; 697 int linepos = 0; 698 699 /* 700 * Limit number of spaces to indent based on line width and the 701 * maximum hexadecimal data width (32 x 3 + 1 null terminator). 702 */ 703 indent = indent > (PTP_UTIL_HEXDUMP_LINE_WIDTH_OCTETS - 97) ? 704 (PTP_UTIL_HEXDUMP_LINE_WIDTH_OCTETS - 97) : indent; 705 706 for (j = 0; j < indent; j++) { 707 sal_sprintf(line+linepos++," "); 708 } 709 for (i = 0; i < len; ++i) { 710 sal_sprintf(line + linepos, "%02x", *buf++); 711 linepos += 2; 712 sal_sprintf(line + linepos, " "); 713 ++linepos; 714 715 if ((i & 0x1f) == 0x1f) { 716 LOG_CLI((BSL_META("%s\n"), line)); 717 line[0] = 0; 718 linepos = 0; 719 for (j = 0; j < indent; j++) { 720 sal_sprintf(line+linepos++," "); 721 } 722 } 723 } 724 725 /* output last line if it wasn't complete */ 726 if (len & 0x1f) { 727 LOG_CLI((BSL_META("%s\n"), line)); 728 } 729 } 730 731 sal_time_t _bcm_ptp_monotonic_time() 732 { 733 static _bcm_ptp_mutex_t mutex = 0; 734 static int32 time_offset = 0; 735 static sal_time_t last_time; 736 static sal_usecs_t last_usecs; 737 sal_time_t this_time = sal_time(), offset_time; 738 sal_usecs_t this_usecs = sal_time_usecs(); 739 int32 usecs_diff, time_diff, time_jump; 740 int rv; 741 742 if (!mutex) { 743 mutex = _bcm_ptp_mutex_create("ptp_monotonic_time"); 744 745 last_time = this_time; 746 last_usecs = this_usecs; 747 } 748 749 rv = _bcm_ptp_mutex_take(mutex, 1000000); /* one second timeout */ 750 751 if (rv != BCM_E_NONE) { 752 LOG_ERROR(BSL_LS_BCM_COMMON, 753 (BSL_META("Failed to get PTP monotonic_time mutex: %d (%s)\n"), rv, bcm_errmsg(rv))); 754 return this_time + time_offset; 755 } 756 757 time_diff = (int32)(this_time - last_time); 758 usecs_diff = (int32)(this_usecs - last_usecs); 759 760 /* if the clock hasn't been adjusted, the difference between these two differences 761 should be zero. If it has been adjusted, the difference is the magnitude of the 762 "time jump" 763 */ 764 time_jump = time_diff - (usecs_diff / 1000000); 765 766 if (time_jump < -2 || time_jump > 2) { 767 LOG_INFO(BSL_LS_BCM_PTP, 768 (BSL_META("Time jumped by %d seconds \n"), (int)time_jump)); 769 770 /* the output of sal_time() evidently jumped, so incorporate that jump into future output */ 771 time_offset -= time_jump; 772 } 773 774 last_time = this_time; 775 last_usecs = this_usecs; 776 777 offset_time = this_time + time_offset; 778 779 _bcm_ptp_mutex_give(mutex); 780 781 return offset_time; 782 } 783 784 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) 785 /* 786 * Function: 787 * _bcm_ptp_check_firmware_exist 788 * Purpose: 789 * Check if the system is running provided firmware 790 * Parameters: 791 * fw_str - (IN) firmware string 792 * Returns: 793 * BCM_E_XXX; 794 * Notes: 795 * Function tells whether the provided firmware 796 * is running on the system, return unavail if not 797 */ 798 799 int 800 _bcm_ptp_check_firmware_exist (char* fw_str) 801 { 802 int uc; 803 char *version = NULL; 804 int firmware = 0; 805 int unit = 0; 806 807 for(uc=0; uc<SOC_INFO(unit).num_ucs; uc++) { 808 if (!soc_uc_in_reset(unit, uc)) { 809 version = soc_uc_firmware_version(unit, uc); 810 if (version) { 811 #ifdef NO_SAL_APPL 812 if (strstr((char *)version,(char *)fw_str)) { 813 #else 814 if (sal_strcasestr((char *)version,(char *)fw_str)) { 815 #endif 816 firmware = 1; 817 } 818 soc_cm_sfree(unit, version); 819 if (1 == firmware) { 820 break; 821 } 822 } 823 } 824 } 825 if (firmware == 0) { 826 return BCM_E_UNAVAIL; 827 } 828 return BCM_E_NONE; 829 } 830 #endif /* BCM_PTP_INTERNAL_STACK_SUPPORT */ 831 #endif /* defined(INCLUDE_PTP)*/