ptp.c (462738B)
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: ptp.c 8 * Purpose: IEEE1588 (PTP) Support 9 */ 10 11 #include <sal/core/dpc.h> 12 #include <sal/core/time.h> 13 #include <appl/diag/system.h> 14 #include <appl/diag/dport.h> 15 #include <shared/bsl.h> 16 #include <bcm/error.h> 17 #include <soc/drv.h> 18 #include <bcm/time.h> 19 20 #if defined(VXWORKS) 21 #include <vxWorks.h> 22 #include <version.h> 23 #include "config.h" 24 #include <time.h> 25 #include <stdlib.h> 26 #define PTP_SAL_HAS_TIME (1) 27 #endif 28 29 #if defined(UNIX) && !defined(__KERNEL__) 30 #include <time.h> 31 #include <stdlib.h> 32 #define PTP_SAL_HAS_TIME (1) 33 #endif 34 35 #if defined(INCLUDE_PTP) 36 37 #include <bcm/ptp.h> 38 #include <bcm_int/common/ptp.h> 39 #include <bcm_int/common/PTP_feature.h> 40 #include <appl/diag/bslenable.h> 41 42 #ifdef BCM_ESMC_EXTDPLL_SUPPORT 43 #include <bcm_int/common/esmc.h> 44 #endif 45 46 #if defined(BCM_KSCPU_SUPPORT) && !defined(PTP_KEYSTONE_STACK) 47 #define PTP_KEYSTONE_STACK 48 #endif 49 50 #define LOCAL_DEBUGBUFSIZE (2048) 51 52 static char local_debugbuf[LOCAL_DEBUGBUFSIZE]; 53 static int local_head = 0; 54 55 static char output_debugbuf[LOCAL_DEBUGBUFSIZE * 2]; 56 static int local_tail = 0; 57 58 bcm_tdpll_input_clock_ql_change_cb_data_t ql_change_data; 59 60 #define BCM_TOD_ETHERTYPE (0x5006) 61 62 #ifndef __KERNEL__ 63 64 STATIC char *bcm_ptp_clock_accuracy_str[] = { 65 "bcmPTPClockAccuracy25ns", 66 "bcmPTPClockAccuracy100ns", 67 "bcmPTPClockAccuracy250ns", 68 "bcmPTPClockAccuracy1us", 69 "bcmPTPClockAccuracy2500ns", 70 "bcmPTPClockAccuracy10us", 71 "bcmPTPClockAccuracy25us", 72 "bcmPTPClockAccuracy100us", 73 "bcmPTPClockAccuracy250us", 74 "bcmPTPClockAccuracy1ms", 75 "bcmPTPClockAccuracy2500us", 76 "bcmPTPClockAccuracy10ms", 77 "bcmPTPClockAccuracy25ms", 78 "bcmPTPClockAccuracy100ms", 79 "bcmPTPClockAccuracy250ms", 80 "bcmPTPClockAccuracy1s", 81 "bcmPTPClockAccuracy10s", 82 "bcmPTPClockAccuracyL10s", 83 "bcmPTPClockAccuracyUnknown", 84 "bcmPTPClockAccuracyReserved", 85 }; 86 87 typedef struct { 88 int synced; 89 sal_time_t host_time; 90 bcm_ptp_timestamp_t ptp_time; 91 } diagshell_sync_t; 92 93 static diagshell_sync_t diagshell_sync; 94 95 STATIC void diag_arp_callback(int unit, bcm_ptp_stack_id_t stack_id, int protocol, int src_addr_offset, int payload_offset, int msg_len, uint8 *msg); 96 97 STATIC int diag_event_callback( 98 int unit, 99 bcm_ptp_stack_id_t stack_id, 100 int clock_num, 101 uint32 clock_port, 102 bcm_ptp_cb_type_t type, 103 bcm_ptp_cb_msg_t *msg, 104 void *user_data); 105 106 STATIC int diag_management_callback( 107 int unit, 108 bcm_ptp_stack_id_t stack_id, 109 int clock_num, 110 uint32 clock_port, 111 bcm_ptp_cb_type_t type, 112 bcm_ptp_cb_msg_t *msg, 113 void *user_data); 114 115 STATIC bcm_ptp_callback_t diag_signaling_arbiter( 116 int unit, 117 bcm_ptp_cb_signaling_arbiter_msg_t *amsg, 118 void * flags); 119 #define ARBITER_DENY_FLAG (0x00000001) 120 121 STATIC int diag_ctdev_alarm_callback( 122 int unit, 123 bcm_ptp_stack_id_t ptp_id, 124 int clock_num, 125 bcm_ptp_ctdev_alarm_data_t *ctdev_alarm_data); 126 127 /* T-DPLL support. */ 128 STATIC int diag_tdpll_input_clock_monitor_callback( 129 int unit, 130 int stack_id, 131 bcm_tdpll_input_clock_monitor_cb_data_t *cb_data); 132 133 STATIC int diag_tdpll_input_clock_callback( 134 int unit, 135 int stack_id, 136 bcm_tdpll_input_clock_cb_data_t *cb_data); 137 138 STATIC int diag_tdpll_input_clock_selector_callback( 139 int unit, 140 int stack_id, 141 bcm_tdpll_input_clock_selector_cb_data_t *cb_data); 142 143 STATIC int diag_tdpll_input_clock_ql_change_callback( 144 int unit, 145 int stack_id, 146 bcm_tdpll_input_clock_ql_change_cb_data_t *cb_data); 147 148 STATIC const char* diag_ieee1588_warn_reason_description(_bcm_ptp_ieee1588_warn_reason_t reason); 149 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 150 STATIC const char* diag_servo_state_description(int state); 151 #else 152 STATIC const char* diag_servo_state_description(bcm_ptp_fll_state_t state); 153 #endif 154 STATIC const char* diag_servo_lock_status_description(bcm_ptp_servo_lock_status_t state); 155 STATIC const char* diag_pps_in_state_description(_bcm_ptp_pps_in_state_t state); 156 157 STATIC const char* diag_telecom_QL_description( 158 const bcm_ptp_telecom_g8265_quality_level_t QL); 159 STATIC const char* diag_telecom_pktmaster_state_description( 160 const bcm_ptp_telecom_g8265_pktmaster_state_t state); 161 STATIC void diag_telecom_pktmaster_printout( 162 bcm_ptp_telecom_g8265_pktmaster_t *pktmaster, uint8 flags); 163 164 STATIC uint32 diag_debug_mask[BCM_MAX_NUM_UNITS][PTP_MAX_STACKS_PER_UNIT] = {{0}}; 165 STATIC uint64 diag_log_mask[BCM_MAX_NUM_UNITS][PTP_MAX_STACKS_PER_UNIT] = {{COMPILER_64_INIT(0,0)}}; 166 167 bcm_mac_t log_dst_mac_addr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 168 bcm_mac_t log_src_mac_addr = {0x00, 0x10, 0x18, 0x00, 0x00, 0x01}; 169 bcm_ip_t log_dst_ip_addr = 0xffffffff; 170 bcm_ip_t log_src_ip_addr = (192L << 24) + (168L << 16) +(0L << 8) + 90; 171 uint32 log_port = 0x4455; 172 uint32 log_tpid = 0x8100; 173 uint32 log_vid = 1; 174 uint32 log_ttl = 1; 175 176 extern void format_uint64_decimal(char *buf, uint64 n, int comma); 177 STATIC char *ptp_clock_accuracy_get(bcm_ptp_clock_accuracy_t *clock_accuracy, char *clock_accuracy_str); 178 #endif 179 180 STATIC const char* diag_port_state_description(_bcm_ptp_port_state_t state); 181 void ptp_print_addr(bcm_ptp_clock_port_address_t addr, char *addrstr); 182 void ptp_print_clockid(bcm_ptp_clock_identity_t id, char *idstr); 183 184 185 #if defined(BCM_TRIDENT2_SUPPORT) 186 int bcm_esw_ptp_map_input_synce_clock(int logical_l1_clk_port); 187 #endif 188 189 /* 190 * Verbose diagnostic shell / CLI information. 191 */ 192 int verboseCLI = 0, verboseEvents = 2; 193 194 #define PTP_VERBOSE(msg) \ 195 do { \ 196 if (verboseCLI) { \ 197 cli_out("%s", msg); \ 198 } \ 199 } while (0) 200 201 #define PTP_CLI_RESULT_RETURN(__cmd_result__) \ 202 do { \ 203 switch (__cmd_result__) { \ 204 case CMD_OK: \ 205 PTP_VERBOSE("PASSED\n"); \ 206 return __cmd_result__; \ 207 case CMD_FAIL: \ 208 PTP_VERBOSE("FAILED\n"); \ 209 return __cmd_result__; \ 210 case CMD_USAGE: \ 211 PTP_VERBOSE("INVALID SYNTAX\n"); \ 212 return __cmd_result__; \ 213 case CMD_NFND: \ 214 PTP_VERBOSE("NOT FOUND\n"); \ 215 return __cmd_result__; \ 216 case CMD_EXIT: \ 217 PTP_VERBOSE("EXIT SHELL\n"); \ 218 return __cmd_result__; \ 219 case CMD_INTR: \ 220 PTP_VERBOSE("INTERRUPTED\n"); \ 221 return __cmd_result__; \ 222 case CMD_NOTIMPL: \ 223 PTP_VERBOSE("NOT IMPLEMENTED\n"); \ 224 return __cmd_result__; \ 225 default: \ 226 PTP_VERBOSE("UNKNOWN\n"); \ 227 return CMD_FAIL; \ 228 } \ 229 } while (0) 230 231 #define PTP_IF_ERROR_RETURN(op) \ 232 do { \ 233 int __rv__; \ 234 if ((__rv__ = (op)) < 0) { \ 235 ptp_printf("Error: %s\n", bcm_errmsg(__rv__)); \ 236 PTP_CLI_RESULT_RETURN(CMD_FAIL); \ 237 } \ 238 } while (0) 239 240 void bcm_ptp_debug_configure(int severity) { 241 bslmgmt_set(BSL_L_BCM, BSL_S_PTP, severity); 242 } 243 244 void 245 ptp_printf(const char *fmt, ...) 246 { 247 int ret; 248 va_list args; 249 char buf[512]; 250 int i; 251 252 va_start(args, fmt); 253 ret = sal_vsprintf(buf, fmt, args); 254 255 for (i = 0; i < ret; ++i) { 256 local_debugbuf[local_head++] = buf[i]; 257 if (local_head >= LOCAL_DEBUGBUFSIZE) local_head = 0; 258 } 259 260 va_end(args); 261 } 262 263 void 264 ptp_print_buf(const char *hdr, const uint8* buf, int len) 265 { 266 while (len > 0) { 267 int i; 268 269 ptp_printf("%s:", hdr); 270 for (i = 0; i < 16 && len > 0; ++i) { 271 ptp_printf(" %02x", (unsigned) *buf); 272 ++buf; 273 --len; 274 } 275 ptp_printf("\n"); 276 } 277 } 278 279 /* Print clock port network address */ 280 void 281 ptp_print_addr(bcm_ptp_clock_port_address_t addr, char *addrstr) 282 { 283 int i; 284 int num; 285 char pstr[4] = {'\0'}; 286 287 addrstr[0] = '\0'; 288 switch (addr.addr_type) { 289 case bcmPTPUDPIPv4: 290 sal_sprintf(addrstr, "%d.%d.%d.%d", 291 addr.address[0], addr.address[1], addr.address[2], addr.address[3]); 292 num = 0; 293 break; 294 case bcmPTPUDPIPv6: 295 num = 15; 296 break; 297 case bcmPTPIEEE8023: 298 num = 5; 299 break; 300 default: 301 num = 0; 302 break; 303 } 304 305 if (0 == num) { 306 return; 307 } 308 309 /* for L2 & IPv6, num > 0, so we print like this: */ 310 for (i = 0; i < num; ++i) { 311 sal_sprintf(pstr, "%02x:", addr.address[i]); 312 sal_strcat(addrstr, pstr); 313 } 314 sal_sprintf(pstr, "%02x", addr.address[num]); 315 sal_strcat(addrstr, pstr); 316 } 317 318 /* Print clock ID */ 319 void 320 ptp_print_clockid(bcm_ptp_clock_identity_t id, char *idstr) 321 { 322 int i; 323 char pstr[4] = {'\0'}; 324 325 idstr[0] = '\0'; 326 for (i = 0; i < 7; ++i) { 327 sal_sprintf(pstr, "%02x:", id[i]); 328 sal_strcat(idstr, pstr); 329 } 330 sal_sprintf(pstr, "%02x", id[7]); 331 sal_strcat(idstr, pstr); 332 } 333 334 /* Mechanism to output information on a event/management callback. bsl_printf / ptp_printf depending on preference */ 335 #define ptp_cb_printf ptp_printf 336 337 #define PTP_ERROR_CB(errmsg) ptp_cb_printf("callback() FAILED %s\n", \ 338 errmsg) 339 340 #define PTP_ERROR_FUNC_CB(func) ptp_cb_printf("callback() FAILED " \ 341 func " returned %d : %s\n", \ 342 rv, bcm_errmsg(rv)) 343 344 #define PTP_WARN_CB(warnmsg) ptp_cb_printf("callback() failed %s\n", \ 345 warnmsg) 346 347 #define PTP_WARN_FUNC_CB(func) ptp_cb_printf("callback() failed " \ 348 func " returned %d : %s\n", \ 349 rv, bcm_errmsg(rv)) 350 351 #define PTP_VERBOSE_CB(msg) \ 352 do { \ 353 if (verboseCLI) { \ 354 ptp_cb_printf("callback() "); \ 355 ptp_cb_printf msg; \ 356 } \ 357 } while (0) 358 359 360 /* Dump anything new in the debug buffers. 361 * owner: The owner if this is being called as a DPC. 362 * time_as_ptr: Recurrence time if a follow-up DPC to this func should be scheduled. 363 * unit_as_ptr: unit 364 */ 365 STATIC void 366 output_current_debug(void* owner, void* time_as_ptr, void *unit_as_ptr, void *unused_2, void* unused_3) 367 { 368 int callback_time = (int)(size_t)time_as_ptr; 369 int unit = (int)(size_t)unit_as_ptr; 370 bcm_ptp_stack_id_t stack_id; 371 372 uint32 head, size; 373 int out_idx = 0; 374 375 /* output the local debug first */ 376 while (local_tail != local_head) { 377 char c = local_debugbuf[local_tail++]; 378 379 if (c) { 380 output_debugbuf[out_idx++] = c; 381 } 382 383 if (local_tail == LOCAL_DEBUGBUFSIZE) { 384 local_tail = 0; 385 } 386 } 387 388 for (stack_id = 0; stack_id < PTP_MAX_STACKS_PER_UNIT; ++stack_id) { 389 /* Ensure that PTP is up & initialized before proceeding */ 390 if (_bcm_common_ptp_unit_array[unit].memstate == PTP_MEMSTATE_INITIALIZED && 391 _bcm_common_ptp_unit_array[unit].stack_array[stack_id].memstate == PTP_MEMSTATE_INITIALIZED) { 392 393 _bcm_ptp_info_t *ptp_info_p = &_bcm_common_ptp_info[unit]; 394 _bcm_ptp_stack_info_t *stack_p = &ptp_info_p->stack_info[stack_id]; 395 396 /* Katana-style shared-mem output */ 397 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 398 /* head is written in externally, so will be in network byte order 399 * size is read externally, so is also network byte order 400 * tail is local, so we'll keep it in local endianness 401 */ 402 head = soc_htonl(stack_p->int_state.log->head); 403 size = soc_htonl(stack_p->int_state.log->size); 404 405 while (stack_p->int_state.log_tail != head) { 406 char c = stack_p->int_state.log->buf[stack_p->int_state.log_tail++]; 407 if (c) { 408 output_debugbuf[out_idx++] = c; 409 } 410 if (stack_p->int_state.log_tail == size) { 411 stack_p->int_state.log_tail = 0; 412 } 413 } 414 } else { 415 416 #if defined(PTP_KEYSTONE_STACK) 417 #define DEBUG_WINDOW_SIZE (1024) 418 #define DEBUG_OFFSET_MASK (DEBUG_WINDOW_SIZE - 1) 419 static uint32 tail[PTP_MAX_STACKS_PER_UNIT] = {0}; 420 const uint32 debug_head_idx_addr = 0x190005a8; 421 const uint32 debug_window_addr = 0x190005ac; 422 void *cookie = stack_p->ext_info.cookie; 423 uint32 head; 424 425 /* get the current head of the debug buffer (written by ToP) */ 426 stack_p->ext_info.read_fn(cookie, debug_head_idx_addr, &head); 427 head &= DEBUG_OFFSET_MASK; 428 429 /* walk our tail up to the current head */ 430 while (tail[stack_id] != head) { 431 uint32 wordval; 432 uint32 addr = debug_window_addr + tail[stack_id]; 433 /* read a byte at "addr", by reading the word that the byte is in, then shifting */ 434 stack_p->ext_info.read_fn(cookie, addr & 0xfffffffc, &wordval); 435 output_debugbuf[out_idx++] = wordval >> (24 - (addr & 3) * 8); 436 tail[stack_id] = ((tail[stack_id] + 1) & DEBUG_OFFSET_MASK); 437 } 438 #endif 439 440 } 441 } 442 443 if (out_idx) { 444 output_debugbuf[out_idx] = 0; 445 /* If UDP logging of debug is enabled, do not print logging on console */ 446 #ifndef __KERNEL__ 447 if ((COMPILER_64_LO(diag_log_mask[unit][stack_id]) & 1) == 0) { 448 cli_out("%s", output_debugbuf); 449 } 450 #else 451 cli_out("%s", output_debugbuf); 452 #endif 453 } 454 } 455 456 sal_dpc_cancel(INT_TO_PTR(&output_current_debug)); 457 if (callback_time) { 458 sal_dpc_time(callback_time, &output_current_debug, 0, time_as_ptr, unit_as_ptr, 0, 0); 459 } 460 } 461 462 463 static cmd_result_t 464 ptp_show_clock(int unit, bcm_ptp_stack_id_t stack_id, int clock_num) 465 { 466 bcm_ptp_clock_info_t clock_info; 467 bcm_ptp_default_dataset_t def_data_set; 468 bcm_ptp_current_dataset_t cur_data_set; 469 bcm_ptp_parent_dataset_t par_data_set; 470 bcm_ptp_time_properties_t tp_data_set; 471 cmd_result_t rv; 472 char uint64_decimal_string[27]; 473 474 if (BCM_FAILURE(rv = bcm_ptp_clock_get(unit,0,clock_num,&clock_info))) { 475 cli_out("\nbcm_ptp_clock_get() Error... (FCN RETURN= %d)\n", rv); 476 PTP_CLI_RESULT_RETURN(CMD_FAIL); 477 } 478 479 /* retrieve clock datasets */ 480 if (BCM_FAILURE(rv = bcm_ptp_clock_default_dataset_get(unit, stack_id, clock_num, &def_data_set))) 481 { 482 cli_out("\nbcm_ptp_clock_default_dataset_get() Error... (FCN RETURN= %d)\n", rv); 483 PTP_CLI_RESULT_RETURN(CMD_FAIL); 484 } 485 486 if (BCM_FAILURE(rv = bcm_ptp_clock_current_dataset_get(unit, stack_id, clock_num, &cur_data_set))) { 487 cli_out("\nbcm_ptp_clock_current_dataset_get() Error... (FCN RETURN= %d)\n", rv); 488 PTP_CLI_RESULT_RETURN(CMD_FAIL); 489 } 490 491 if (BCM_FAILURE(rv = bcm_ptp_clock_parent_dataset_get(unit, stack_id, clock_num, &par_data_set))) { 492 cli_out("\nbcm_ptp_clock_parent_dataset_get() Error... (FCN RETURN= %d)\n", rv); 493 PTP_CLI_RESULT_RETURN(CMD_FAIL); 494 } 495 496 if (BCM_FAILURE(rv = bcm_ptp_clock_time_properties_get(unit, stack_id, clock_num, &tp_data_set))) { 497 cli_out("\nbcm_ptp_clock_time_properties_get() Error... (FCN RETURN= %d)\n", rv); 498 PTP_CLI_RESULT_RETURN(CMD_FAIL); 499 } 500 501 if (BCM_FAILURE(rv = bcm_ptp_clock_get(unit, stack_id, clock_num, &clock_info))) { 502 cli_out("\nbcm_ptp_clock_get() Error... (FCN RETURN= %d)\n", rv); 503 PTP_CLI_RESULT_RETURN(CMD_FAIL); 504 } 505 506 cli_out("\nClock Instance DataSets\n\n"); 507 508 /* Default Dataset */ 509 cli_out(" defaultDS.twoStepFlag : %s\n", 510 def_data_set.flags & BCM_PTP_DATASET_TWOSTEP_ONLY ? "TRUE" : "FALSE"); 511 512 cli_out(" defaultDS.clockIdentity : %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 513 def_data_set.clock_identity[0], def_data_set.clock_identity[1], 514 def_data_set.clock_identity[2], def_data_set.clock_identity[3], 515 def_data_set.clock_identity[4], def_data_set.clock_identity[5], 516 def_data_set.clock_identity[6], def_data_set.clock_identity[7]); 517 518 cli_out(" defaultDS.numberPorts : %u\n", def_data_set.number_ports); 519 520 cli_out(" defaultDS.clockQuality.clockClass : %u\n", 521 def_data_set.clock_quality.clock_class); 522 cli_out(" defaultDS.clockQuality.clockAccuracy : %u\n", 523 def_data_set.clock_quality.clock_accuracy); 524 cli_out(" defaultDS.clockQuality.offsetScaledLogVariance : %u\n", 525 def_data_set.clock_quality.offset_scaled_log_variance); 526 527 cli_out(" defaultDS.priority1 : %u\n", def_data_set.priority1); 528 cli_out(" defaultDS.priority2 : %u\n", def_data_set.priority2); 529 cli_out(" defaultDS.localpriority : %u\n", def_data_set.local_priority); 530 cli_out(" defaultDS.maxStepsRemoved : %u\n", def_data_set.max_steps_removed); 531 cli_out(" defaultDS.domainNumber : %u\n", def_data_set.domain_number); 532 533 cli_out(" defaultDS.slaveOnly : %s\n", 534 def_data_set.flags & BCM_PTP_DATASET_SLAVE_ONLY ? "TRUE" : "FALSE"); 535 536 cli_out("\n"); 537 538 /* Current Dataset */ 539 cli_out(" currentDS.stepsRemoved : %u\n", cur_data_set.steps_removed); 540 format_uint64_decimal(uint64_decimal_string, cur_data_set.offset_from_master, ','); 541 cli_out(" currentDS.offsetFromMaster : %s\n", uint64_decimal_string); 542 #ifdef COMPILER_HAS_LONGLONG 543 cli_out(" currentDS.meanPathDelay : %lld\n", (long long)cur_data_set.mean_path_delay); 544 #endif 545 546 cli_out("\n"); 547 548 /* Parent Dataset */ 549 550 cli_out(" parentDS.parentPortIdentity.clockIdentity : %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 551 par_data_set.parent_port_identity.clock_identity[0], 552 par_data_set.parent_port_identity.clock_identity[1], 553 par_data_set.parent_port_identity.clock_identity[2], 554 par_data_set.parent_port_identity.clock_identity[3], 555 par_data_set.parent_port_identity.clock_identity[4], 556 par_data_set.parent_port_identity.clock_identity[5], 557 par_data_set.parent_port_identity.clock_identity[6], 558 par_data_set.parent_port_identity.clock_identity[7]); 559 560 cli_out(" parentDS.parentPortIdentity.portNumber : %u\n", 561 par_data_set.parent_port_identity.port_number); 562 cli_out(" parentDS.parentStats : %s\n", 563 par_data_set.ps & 0x01 ? "TRUE" : "FALSE"); 564 cli_out(" parentDS.observedParentOffsetScaledLogVariance : %u\n", 565 par_data_set.observed_parent_offset_scaled_log_variance); 566 cli_out(" parentDS.observedParentClockPhaseChangeRate : %u\n", 567 par_data_set.observed_parent_clock_phase_change_rate); 568 569 cli_out(" parentDS.grandmasterIdentity : %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 570 par_data_set.grandmaster_identity[0], par_data_set.grandmaster_identity[1], 571 par_data_set.grandmaster_identity[2], par_data_set.grandmaster_identity[3], 572 par_data_set.grandmaster_identity[4], par_data_set.grandmaster_identity[5], 573 par_data_set.grandmaster_identity[6], par_data_set.grandmaster_identity[7]); 574 575 cli_out(" parentDS.grandmasterClockQuality.clockClass : %u\n", 576 par_data_set.grandmaster_clock_quality.clock_class); 577 cli_out(" parentDS.grandmasterClockQuality.clockAccuracy : %u\n", 578 par_data_set.grandmaster_clock_quality.clock_accuracy); 579 cli_out(" parentDS.grandmasterClockQuality.offsetScaledLogVariance : %u\n", 580 par_data_set.grandmaster_clock_quality.offset_scaled_log_variance); 581 582 cli_out(" parentDS.grandmasterPriority1 : %u\n", 583 par_data_set.grandmaster_priority1); 584 cli_out(" parentDS.grandmasterPriority2 : %u\n", 585 par_data_set.grandmaster_priority2); 586 587 cli_out("\n"); 588 589 /* Time Properties Dataset */ 590 591 cli_out(" timePropertiesDS.currentUtcOffset : %d\n", 592 tp_data_set.utc_info.utc_offset); 593 cli_out(" timePropertiesDS.currentUtcOffsetValid : %s\n", 594 tp_data_set.utc_info.utc_valid ? "TRUE" : "FALSE"); 595 cli_out(" timePropertiesDS.leap59 : %s\n", 596 tp_data_set.utc_info.leap59 ? "TRUE" : "FALSE"); 597 cli_out(" timePropertiesDS.leap61 : %s\n", 598 tp_data_set.utc_info.leap61 ? "TRUE" : "FALSE"); 599 cli_out(" timePropertiesDS.timeTraceable : %s\n", 600 tp_data_set.trace_info.time_traceable ? "TRUE" : "FALSE"); 601 cli_out(" timePropertiesDS.frequencyTraceable : %s\n", 602 tp_data_set.trace_info.frequency_traceable ? "TRUE" : "FALSE"); 603 cli_out(" timePropertiesDS.ptpTimescale : %s\n", 604 tp_data_set.timescale_info.ptp_timescale ? "TRUE" : "FALSE"); 605 cli_out(" timeProperitesDS.timeSource : 0x%02x\n", 606 tp_data_set.timescale_info.time_source); 607 608 cli_out(" timeProperitesDS.masterSyncUncertain : %s\n", 609 (tp_data_set.ptp_pkt_flags & (1<<BCM_PTP_PKT_FLAG_SYNC_UNCERTAIN)) 610 ? "TRUE" : "FALSE"); 611 612 cli_out("\nClock Instance Parameters\n\n"); 613 614 cli_out(" Clock Num : %u\n", clock_info.clock_num); 615 616 cli_out(" Clock Identity : %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 617 clock_info.clock_identity[0], 618 clock_info.clock_identity[1], 619 clock_info.clock_identity[2], 620 clock_info.clock_identity[3], 621 clock_info.clock_identity[4], 622 clock_info.clock_identity[5], 623 clock_info.clock_identity[6], 624 clock_info.clock_identity[7]); 625 626 cli_out(" Clock Type : %u", clock_info.type); 627 if (clock_info.type== bcmPTPClockTypeOrdinary) { 628 cli_out(" (Ordinary)\n"); 629 } else if (clock_info.type== bcmPTPClockTypeBoundary){ 630 cli_out(" (Boundary)\n"); 631 } else if (clock_info.type== bcmPTPClockTypeTransparent){ 632 cli_out(" (Transparent)\n"); 633 } else { 634 cli_out(" (Unknown)\n"); 635 } 636 637 cli_out("\n"); 638 cli_out(" TC Primary Domain : %u\n", clock_info.tc_primary_domain); 639 cli_out(" TC Delay Mechanism : %u\n", clock_info.tc_delay_mechanism); 640 cli_out("\n"); 641 cli_out(" Announce Receipt Timeout (MINIMUM) : %u\n", clock_info.announce_receipt_timeout_minimum); 642 cli_out(" Announce Receipt Timeout (DEFAULT) : %u\n", clock_info.announce_receipt_timeout_default); 643 cli_out(" Announce Receipt Timeout (MAXIMUM) : %u\n", clock_info.announce_receipt_timeout_maximum); 644 cli_out("\n"); 645 cli_out(" Log Announce Interval (MINIMUM) : %d\n", clock_info.log_announce_interval_minimum); 646 cli_out(" Log Announce Interval (DEFAULT) : %d\n", clock_info.log_announce_interval_default); 647 cli_out(" Log Announce Interval (MAXIMUM) : %d\n", clock_info.log_announce_interval_maximum); 648 cli_out("\n"); 649 cli_out(" Log Sync Interval (MINIMUM) : %d\n", clock_info.log_sync_interval_minimum); 650 cli_out(" Log Sync Interval (DEFAULT) : %d\n", clock_info.log_sync_interval_default); 651 cli_out(" Log Sync Interval (MAXIMUM) : %d\n", clock_info.log_sync_interval_maximum); 652 cli_out("\n"); 653 cli_out(" Log Min Delay Req Interval (MINIMUM): %d\n", clock_info.log_min_delay_req_interval_minimum); 654 cli_out(" Log Min Delay Req Interval (DEFAULT): %d\n", clock_info.log_min_delay_req_interval_default); 655 cli_out(" Log Min Delay Req Interval (MAXIMUM): %d\n", clock_info.log_min_delay_req_interval_maximum); 656 cli_out("\n"); 657 cli_out(" Domain # (MINIMUM) : %u\n", clock_info.domain_number_minimum); 658 cli_out(" Domain # (DEFAULT) : %u\n", clock_info.domain_number_default); 659 cli_out(" Domain # (MAXIMUM) : %u\n", clock_info.domain_number_maximum); 660 cli_out("\n"); 661 cli_out(" Priority 1 (MINIMUM) : %u\n", clock_info.priority1_minimum); 662 cli_out(" Priority 1 (DEFAULT) : %u\n", clock_info.priority1_default); 663 cli_out(" Priority 1 (MAXIMUM) : %u\n", clock_info.priority1_maximum); 664 cli_out("\n"); 665 cli_out(" Priority 2 (MINIMUM) : %u\n", clock_info.priority2_minimum); 666 cli_out(" Priority 2 (DEFAULT) : %u\n", clock_info.priority2_default); 667 cli_out(" Priority 2 (MAXIMUM) : %u\n", clock_info.priority2_maximum); 668 cli_out("\n"); 669 cli_out(" Flags : 0x%08x\n", clock_info.flags); 670 cli_out("\n"); 671 cli_out(" LocalPriority : %u\n", clock_info.local_priority); 672 cli_out("\n"); 673 674 /* cli_out(" # Virtual Interfaces : %u\n", clock_info.number_virtual_interfaces); */ 675 PTP_CLI_RESULT_RETURN(CMD_OK); 676 } 677 678 STATIC const char* 679 diag_tod_format_description( 680 bcm_ptp_tod_format_t tod_fmt ) 681 { 682 switch (tod_fmt) { 683 case bcmPTPTODFormatString: 684 return "bcmPTPTODFormatString"; 685 686 case bcmPTPTODFormatUBlox: 687 return "bcmPTPTODFormatUBlox"; 688 689 case bcmPTPTODFormatChinaTcom: 690 return "bcmPTPTODFormatChinaTcom"; 691 692 case bcmPTPTODFormatBCM: 693 return "bcmPTPTODFormatBCM"; 694 695 case bcmPTPTODFormatBCMTS: 696 return "bcmPTPTODFormatBCMTS"; 697 698 case bcmPTPTODFormatG8271: 699 return "bcmPTPTODFormatG8271"; 700 701 default: 702 return "<Unknown>"; 703 } 704 } 705 706 STATIC cmd_result_t 707 ptp_show_port(int unit, bcm_ptp_stack_id_t stack_id, int clock_num, int port_number) 708 { 709 bcm_ptp_port_dataset_t port_data_set; 710 bcm_ptp_clock_port_info_t port_data_api; 711 #ifndef __KERNEL__ 712 _bcm_ptp_clock_description_t description; 713 #endif 714 cmd_result_t rv; 715 char uint64_decimal_string[27]; 716 717 /* Retrieve comprehensive port configuration information to use in report. */ 718 if (BCM_FAILURE(rv = bcm_ptp_clock_port_info_get(unit, stack_id, clock_num, 719 port_number, &port_data_api))) { 720 cli_out("\nbcm_ptp_clock_port_info_get() Error... (FCN RETURN= %d)\n", rv); 721 PTP_CLI_RESULT_RETURN(CMD_FAIL); 722 } 723 724 if (BCM_FAILURE(rv = bcm_ptp_clock_port_dataset_get(unit, stack_id, clock_num, port_number, &port_data_set))) { 725 cli_out("\nbcm_ptp_clock_port_dataset_get(%d, %d, %d, %d, &dataset) Error... (FCN RETURN= %d)\n", 726 unit, stack_id, clock_num, port_number, rv); 727 PTP_CLI_RESULT_RETURN(CMD_FAIL); 728 } 729 730 cli_out("\nClock Port %d DataSets\n\n", port_number); 731 732 cli_out(" portDS.portIdentity : %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%04x\n", 733 port_data_set.port_identity.clock_identity[0], 734 port_data_set.port_identity.clock_identity[1], 735 port_data_set.port_identity.clock_identity[2], 736 port_data_set.port_identity.clock_identity[3], 737 port_data_set.port_identity.clock_identity[4], 738 port_data_set.port_identity.clock_identity[5], 739 port_data_set.port_identity.clock_identity[6], 740 port_data_set.port_identity.clock_identity[7], 741 port_data_set.port_identity.port_number); 742 743 cli_out(" portDS.portState : %s\n", diag_port_state_description(port_data_set.port_state)); 744 cli_out(" portDS.logMinDelayReqInterval : %d\n", port_data_set.log_min_delay_req_interval); 745 format_uint64_decimal(uint64_decimal_string, port_data_set.peer_mean_path_delay, ','); 746 cli_out(" portDS.peerMeanPathDelay : %s\n", uint64_decimal_string); 747 cli_out(" portDS.logAnnounceInterval : %d\n", port_data_set.log_announce_interval); 748 cli_out(" portDS.announceReceiptTimeout : %d\n", port_data_set.announce_receipt_timeout); 749 cli_out(" portDS.logSyncInterval : %d\n", port_data_set.log_sync_interval); 750 cli_out(" portDS.delayMechanism : %u", port_data_set.delay_mechanism); 751 if (port_data_set.delay_mechanism == bcmPTPDelayMechanismEnd2End) { 752 cli_out(" (End-to-End)\n"); 753 } else if (port_data_set.delay_mechanism == bcmPTPDelayMechanismPeer2Peer) { 754 cli_out(" (Peer-to-Peer)\n"); 755 } else if (port_data_set.delay_mechanism == bcmPTPDelayMechansimDisabled) { 756 cli_out(" (Disabled)\n"); 757 } else { 758 cli_out(" (Unknown)\n"); 759 } 760 cli_out(" portDS.logMinPDelayReqInterval : %d\n", port_data_set.log_min_pdelay_req_interval); 761 cli_out(" portDS.versionNumber : %d\n", port_data_set.version_number); 762 cli_out(" portDS.localPriority : %d\n", port_data_set.local_priority); 763 cli_out(" portDS.notSlave : %s\n", port_data_set.not_slave ? "TRUE" : "FALSE"); 764 cli_out(" portDS.SF : %s\n", (port_data_set.signal_fail>0) ? "TRUE" : "FALSE"); 765 766 cli_out("\nClock Port %d Parameters\n\n", port_number); 767 768 cli_out(" Port Address Protocol : %u",port_data_api.port_address.addr_type); 769 if (port_data_api.port_address.addr_type == bcmPTPIEEE8023) { 770 cli_out(" (Ethernet Layer 2)\n"); 771 } else if (port_data_api.port_address.addr_type == bcmPTPUDPIPv4) { 772 cli_out(" (Ethernet/UDP/IPv4)\n"); 773 } else if (port_data_api.port_address.addr_type == bcmPTPUDPIPv6) { 774 cli_out(" (Ethernet/UDP/IPv6)\n"); 775 } else { 776 cli_out(" (Unknown)\n"); 777 } 778 779 if (port_data_api.port_address.addr_type == bcmPTPUDPIPv4) { 780 cli_out(" Port IP Address (IPv4) : %u.%u.%u.%u\n", 781 port_data_api.port_address.address[0], port_data_api.port_address.address[1], 782 port_data_api.port_address.address[2], port_data_api.port_address.address[3]); 783 } else if (port_data_api.port_address.addr_type == bcmPTPUDPIPv6) { 784 cli_out(" Port IP Address (IPv6) : %02x%02x:%02x%02x:%02x%02x:%02x%02x:" 785 "%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", 786 port_data_api.port_address.address[0], port_data_api.port_address.address[1], 787 port_data_api.port_address.address[2], port_data_api.port_address.address[3], 788 port_data_api.port_address.address[4], port_data_api.port_address.address[5], 789 port_data_api.port_address.address[6], port_data_api.port_address.address[7], 790 port_data_api.port_address.address[8], port_data_api.port_address.address[9], 791 port_data_api.port_address.address[10], port_data_api.port_address.address[11], 792 port_data_api.port_address.address[12], port_data_api.port_address.address[13], 793 port_data_api.port_address.address[14], port_data_api.port_address.address[15]); 794 } 795 796 cli_out(" Port MAC Address : %02x:%02x:%02x:%02x:%02x:%02x\n", 797 port_data_api.mac[0], port_data_api.mac[1], port_data_api.mac[2], 798 port_data_api.mac[3], port_data_api.mac[4], port_data_api.mac[5]); 799 800 if (port_data_api.multicast_tx_enable) { 801 cli_out(" Multicast L2 Header : |%02x:%02x:%02x:%02x:%02x:%02x|%02x:" 802 "%02x:%02x:%02x:%02x:%02x|%02x:%02x:%02x:%02x|%02x:%02x|\n", 803 port_data_api.multicast_l2[0], port_data_api.multicast_l2[1], 804 port_data_api.multicast_l2[2], port_data_api.multicast_l2[3], 805 port_data_api.multicast_l2[4], port_data_api.multicast_l2[5], 806 port_data_api.multicast_l2[6], port_data_api.multicast_l2[7], 807 port_data_api.multicast_l2[8], port_data_api.multicast_l2[9], 808 port_data_api.multicast_l2[10], port_data_api.multicast_l2[11], 809 port_data_api.multicast_l2[12], port_data_api.multicast_l2[13], 810 port_data_api.multicast_l2[14], port_data_api.multicast_l2[15], 811 port_data_api.multicast_l2[16], port_data_api.multicast_l2[17]); 812 cli_out(" Multicast Pdelay L2 Header : |%02x:%02x:%02x:%02x:%02x:%02x|%02x:" 813 "%02x:%02x:%02x:%02x:%02x|%02x:%02x:%02x:%02x|%02x:%02x|\n", 814 port_data_api.multicast_pdelay_l2[0], port_data_api.multicast_pdelay_l2[1], 815 port_data_api.multicast_pdelay_l2[2], port_data_api.multicast_pdelay_l2[3], 816 port_data_api.multicast_pdelay_l2[4], port_data_api.multicast_pdelay_l2[5], 817 port_data_api.multicast_pdelay_l2[6], port_data_api.multicast_pdelay_l2[7], 818 port_data_api.multicast_pdelay_l2[8], port_data_api.multicast_pdelay_l2[9], 819 port_data_api.multicast_pdelay_l2[10], port_data_api.multicast_pdelay_l2[11], 820 port_data_api.multicast_pdelay_l2[12], port_data_api.multicast_pdelay_l2[13], 821 port_data_api.multicast_pdelay_l2[14], port_data_api.multicast_pdelay_l2[15], 822 port_data_api.multicast_pdelay_l2[16], port_data_api.multicast_pdelay_l2[17]); 823 } else { 824 cli_out(" Multicast Disabled\n"); 825 } 826 827 cli_out(" Port Type : %u", port_data_api.port_type); 828 if (port_data_api.port_type == bcmPTPPortTypeStandard) { 829 cli_out(" (Standard)\n"); 830 } else if (port_data_api.port_type == bcmPTPPortTypeMasterOnly) { 831 cli_out(" (Master-only)\n"); 832 } else if (port_data_api.port_type == bcmPTPPortTypeSlaveOnly) { 833 cli_out(" (Slave-only)\n"); 834 } else if (port_data_api.port_type == bcmPTPPortTypeVirtual) { 835 cli_out(" (Virtual)\n"); 836 } else if (port_data_api.port_type == bcmPTPPortTypeCustomizedVirtual) { 837 cli_out(" (Customized Virtual)\n"); 838 } else { 839 cli_out(" (Unknown)\n"); 840 } 841 842 cli_out(" Rx Timestamp Mechanism : 0x%02x", port_data_api.rx_timestamp_mechanism); 843 if (port_data_api.rx_timestamp_mechanism == bcmPTPToPTimestamps) { 844 cli_out(" (ToP)\n"); 845 } else if (port_data_api.rx_timestamp_mechanism == bcmPTPRCPUTimestamps) { 846 cli_out(" (RCPU)\n"); 847 } else if (port_data_api.rx_timestamp_mechanism == bcmPTPPhyCorrectionTimestamps) { 848 cli_out(" (PHY Correction)\n"); 849 } else if (port_data_api.rx_timestamp_mechanism == bcmPTPMac32CorrectionTimestamps) { 850 cli_out(" (Mac32 Correction)\n"); 851 } else if (port_data_api.rx_timestamp_mechanism == bcmPTPMac48CorrectionTimestamps) { 852 cli_out(" (Mac48 Correction)\n"); 853 } else { 854 cli_out(" (Unknown)\n"); 855 } 856 857 cli_out(" Rx Packets VLAN : 0x%04x\n", port_data_api.rx_packets_vlan); 858 cli_out(" Rx Packets Port Mask (High 32 Bits): 0x%08x\n", port_data_api.rx_packets_port_mask_high32); 859 cli_out(" Rx Packets Port Mask (Low 32 Bits) : 0x%08x\n", port_data_api.rx_packets_port_mask_low32); 860 cli_out(" Rx Packets Criteria Mask : 0x%02x\n", port_data_api.rx_packets_criteria_mask); 861 cli_out(" localPriority : %d\n", port_data_api.local_priority); 862 863 if (port_data_api.port_type == bcmPTPPortTypeVirtual || 864 port_data_api.port_type == bcmPTPPortTypeCustomizedVirtual) { 865 cli_out(" Virtual port configuration\n"); 866 cli_out(" Clock class : %d\n", port_data_api.vport_info.clock_class); 867 cli_out(" Clock accuracy : %d\n", port_data_api.vport_info.clock_accuracy); 868 cli_out(" OffsetScaledLogVariance : %d\n", port_data_api.vport_info.offset_scaled_log_variance); 869 cli_out(" Steps Removed : %d\n", port_data_api.vport_info.steps_removed); 870 cli_out(" GM priority2 : %d\n", port_data_api.vport_info.GM_prio2); 871 cli_out(" TOD offset sec : %d\n", port_data_api.vport_info.tod_offset_sec); 872 cli_out(" TOD offset nsec : %d\n", port_data_api.vport_info.tod_offset_ns); 873 cli_out(" TOD format : %s\n", diag_tod_format_description(port_data_api.vport_info.format)); 874 if (bcmPTPTODFormatString == port_data_api.vport_info.format) { 875 cli_out(" TOD format string : %s\n", port_data_api.vport_info.format_str); 876 cli_out(" TOD mask string : %s\n", port_data_api.vport_info.mask_str); 877 } 878 cli_out(" TOD Ether type : 0x%04x\n", port_data_api.vport_info.ether_type); 879 cli_out(" 1PPS GPIO# : %d\n", port_data_api.vport_info.onepps_in_gpio); 880 if(PTP_UC_FEATURE_CHECK(PTP_VP_TOD_IN_SERIAL)) { 881 if (port_data_api.vport_info.tod_source == bcmPTPTODSourceNone) { 882 cli_out(" TOD source# : %s\n","None"); 883 } else if (port_data_api.vport_info.tod_source == bcmPTPTODSourceEthernet) 884 cli_out(" TOD source# : %s\n","Ethernet"); 885 else { 886 if (port_data_api.vport_info.tod_source == bcmPTPTODSourceSerial) 887 cli_out(" TOD source# : %s\n","UartNum0"); 888 else if (port_data_api.vport_info.tod_source == bcmPTPTODSourceSerial1) 889 cli_out(" TOD source# : %s\n","UartNum1"); 890 else if (port_data_api.vport_info.tod_source == bcmPTPTODSourceSerial2) 891 cli_out(" TOD source# : %s\n","UartNum2"); 892 else if (port_data_api.vport_info.tod_source == bcmPTPTODSourceSerial3) 893 cli_out(" TOD source# : %s\n","UartNum3"); 894 cli_out(" Baud Rate# : %d\n", port_data_api.vport_info.tod_baud_rate); 895 } 896 } 897 } 898 #ifndef __KERNEL__ 899 if (BCM_FAILURE(rv = _bcm_ptp_clock_description_get(unit, stack_id, clock_num, 900 port_number, &description))) { 901 cli_out("\n_bcm_ptp_clock_description_get() Error... (FCN RETURN= %d)\n", rv); 902 PTP_CLI_RESULT_RETURN(CMD_FAIL); 903 } 904 905 cli_out("\nClock Description\n"); 906 _bcm_ptp_dump_hex(description.data, description.size, 3); 907 sal_free(description.data); 908 cli_out("\n"); 909 #endif 910 PTP_CLI_RESULT_RETURN(CMD_OK); 911 } 912 913 914 STATIC cmd_result_t 915 ptp_show_peers(int unit, bcm_ptp_stack_id_t stack_id, int clock_num) 916 { 917 PTP_CLI_RESULT_RETURN(CMD_OK); 918 } 919 920 921 #ifndef __KERNEL__ 922 STATIC char *ptp_clock_accuracy_get(bcm_ptp_clock_accuracy_t *clock_accuracy, char *clock_accuracy_str) 923 { 924 int len = 0; 925 if (*clock_accuracy >= bcmPTPClockAccuracy25ns && 926 *clock_accuracy <= bcmPTPClockAccuracyL10s) { 927 len = sal_strlen(bcm_ptp_clock_accuracy_str[(int)(*clock_accuracy- bcmPTPClockAccuracy25ns)]); 928 sal_strncpy(clock_accuracy_str, 929 bcm_ptp_clock_accuracy_str[(int)(*clock_accuracy 930 - bcmPTPClockAccuracy25ns)], len); 931 if (len) 932 clock_accuracy_str[len] = '\0'; 933 } 934 else { 935 len = sal_strlen("bcmPTPClockAccuracyUnknown/bcmPTPClockAccuracyReserved"); 936 sal_strncpy(clock_accuracy_str, 937 "bcmPTPClockAccuracyUnknown/bcmPTPClockAccuracyReserved", len); 938 if (len) 939 clock_accuracy_str[len] = '\0'; 940 } 941 return (clock_accuracy_str); 942 } 943 STATIC cmd_result_t 944 ptp_show_foreign_master_dataset(int unit, bcm_ptp_stack_id_t stack_id, int clock_num, int port_num) 945 { 946 bcm_ptp_foreign_master_dataset_t dataset; 947 unsigned index; 948 char clock_accuracy_str[64]; 949 950 char idstr[32] = {'\0'}; 951 char addrstr[64] = {'\0'}; 952 953 BCM_IF_ERROR_RETURN( 954 bcm_ptp_foreign_master_dataset_get(unit, stack_id, clock_num, port_num, &dataset)); 955 956 cli_out("Number of Foreign Masters: %d\n", dataset.num_foreign_masters); 957 if (dataset.num_foreign_masters) { 958 cli_out("Current Foreign Master : %d\n", dataset.current_best_master); 959 } else { 960 cli_out("Current Foreign Master :\n"); 961 } 962 for (index = 0; index < dataset.num_foreign_masters; index++) { 963 cli_out("Foreign Master #%d\n", index); 964 965 ptp_print_clockid( 966 dataset.foreign_master[index].port_identity.clock_identity, idstr); 967 cli_out(" Port ID : %s:%04x\n", idstr, 968 dataset.foreign_master[index].port_identity.port_number); 969 970 ptp_print_addr(dataset.foreign_master[index].address, addrstr); 971 cli_out(" Address : %s\n", addrstr); 972 973 cli_out(" clockClass: %u\n", dataset.foreign_master[index].clockClass); 974 cli_out(" priority1 : %u\n", dataset.foreign_master[index].grandmasterPriority1); 975 cli_out(" priority2 : %u\n", dataset.foreign_master[index].grandmasterPriority2); 976 977 { 978 int syncSec = dataset.foreign_master[index].ms_since_sync / 1000; 979 int syncMS = dataset.foreign_master[index].ms_since_sync - 1000 * syncSec; 980 981 int syncTSSec = dataset.foreign_master[index].ms_since_sync_ts / 1000; 982 int syncTSMS = dataset.foreign_master[index].ms_since_sync_ts - 1000 * syncTSSec; 983 984 int delRespSec = dataset.foreign_master[index].ms_since_del_resp / 1000; 985 int delRespMS = dataset.foreign_master[index].ms_since_del_resp - 1000 * delRespSec; 986 987 if (dataset.foreign_master[index].ms_since_del_resp == ((uint32)-1)) { 988 /* 989 * One-way operation. 990 * Delay request and delay response messages are not exchanged. 991 * Firmware overwrites time since last delayResp with all-ones. 992 */ 993 cli_out(" Time since: Sync: %d.%03d Sync/Followup: %d.%03d DelayResp: N/A\n", 994 syncSec, syncMS, syncTSSec, syncTSMS); 995 } else { 996 cli_out(" Time since: Sync: %d.%03d Sync/Followup: %d.%03d DelayResp: %d.%03d sec\n", 997 syncSec, syncMS, syncTSSec, syncTSMS, delRespSec, delRespMS); 998 } 999 1000 cli_out(" Announces : %u (per FOREIGN_MASTER_TIME_WINDOW)\n", 1001 dataset.foreign_master[index].announce_messages); 1002 1003 #ifdef COMPILER_HAS_LONGLONG 1004 if (COMPILER_64_LO(dataset.foreign_master[index].pdv_scaled_allan_var) == ((uint32)-1) && 1005 COMPILER_64_HI(dataset.foreign_master[index].pdv_scaled_allan_var) == ((uint32)-1)) { 1006 cli_out(" MTSD Scaled AVAR: N/A\n"); 1007 } else { 1008 cli_out(" MTSD Scaled AVAR: %llu (nsec-sq)\n", 1009 (long long unsigned)dataset.foreign_master[index].pdv_scaled_allan_var); 1010 } 1011 #endif /* COMPILER_HAS_LONGLONG */ 1012 1013 } 1014 1015 cli_out(" Offset scaled log variance: %u\n", 1016 dataset.foreign_master[index].offset_scaled_log_variance); 1017 cli_out(" Clock accuracy: 0x%02x %s\n", 1018 dataset.foreign_master[index].clock_accuracy, 1019 ptp_clock_accuracy_get(&(dataset.foreign_master[index].clock_accuracy), clock_accuracy_str)); 1020 cli_out(" Steps removed: %u\n", dataset.foreign_master[index].steps_removed); 1021 cli_out(" Grandmaster clockIdentity: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 1022 dataset.foreign_master[index].grandmaster_identity[0], dataset.foreign_master[index].grandmaster_identity[1], 1023 dataset.foreign_master[index].grandmaster_identity[2], dataset.foreign_master[index].grandmaster_identity[3], 1024 dataset.foreign_master[index].grandmaster_identity[4], dataset.foreign_master[index].grandmaster_identity[5], 1025 dataset.foreign_master[index].grandmaster_identity[6], dataset.foreign_master[index].grandmaster_identity[7]); 1026 1027 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 1028 cli_out(" Module Number: %u\n", 1029 BCM_GPORT_MODPORT_MODID_GET(dataset.foreign_master[index].phy_port)); 1030 cli_out(" Physical Port number: %u\n", 1031 BCM_GPORT_MODPORT_PORT_GET(dataset.foreign_master[index].phy_port)); 1032 } 1033 } 1034 1035 PTP_CLI_RESULT_RETURN(CMD_OK); 1036 } 1037 #endif 1038 1039 static int cur_clock_num = 0; /* for now: per-clock operations happen on the last created clock */ 1040 static int cur_stack_id = 0; /* and per-stack operations on the last created stack */ 1041 static int cur_port_num = 1; 1042 1043 typedef struct { 1044 char *str; 1045 cmd_result_t (*func)(int unit, args_t *args); 1046 const char* help; 1047 const char* help_ext; /* To prevent strings > 255 chars */ 1048 } subcommand_t; 1049 1050 static subcommand_t *subcommands_list; /* Null terminated list */ 1051 1052 /* PTP Stack */ 1053 #define PTP_STACK_USAGE \ 1054 "PTP Stack <subcommand>\n" \ 1055 "\t PTP Stack Create TS0TS1CombinedModeEn=<0/1> Creates a PTP Stack\n" \ 1056 "\t PTP Stack Perfomance Prints ToP CPU and Memory Info to debug\n" 1057 1058 STATIC cmd_result_t 1059 cmd_ptp_stack(int unit, args_t *a) 1060 { 1061 int rv; 1062 const char * arg; 1063 parse_table_t pt; 1064 int arg_ts0_ts1_combined_mode_en= 0; 1065 bcm_ptp_stack_info_t stack_info; 1066 1067 arg = ARG_GET(a); 1068 if (!arg) { 1069 PTP_CLI_RESULT_RETURN(CMD_USAGE); 1070 } 1071 if (parse_cmp("Create", arg, 0)) { 1072 #if defined(PTP_KEYSTONE_STACK) 1073 bcm_ptp_external_stack_info_t external = { 1074 0x0002, 0, 1075 0x0800,0x3150,0x8100, 1076 3,0,0x5001, 1077 {0xaa,0xbb,0xcc,0xdd,0xee,0xff}, 1078 {0x00,0x1b,0xe9,0x58,0xb0,0x6d}, 1079 {0x10,0x04,0x9f,0x00,0x01,0x01}, 1080 (192<<24)+(168<<16)+(0<<8)+98, 1081 (192<<24)+(168<<16)+(1<<8)+(1<<0) 1082 ,24 1083 }; 1084 bcm_mac_t switch_mac = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; 1085 #endif 1086 parse_table_init(unit, &pt); 1087 parse_table_add(&pt, "TS0TS1CombinedModeEn", PQ_INT, (void*)0, &arg_ts0_ts1_combined_mode_en, NULL); 1088 if (parse_arg_eq(a, &pt) < 0) { 1089 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 1090 } 1091 1092 if (arg_ts0_ts1_combined_mode_en > 1) { 1093 parse_arg_eq_done(&pt); 1094 cli_out("\n Error in setting ts0 ts1 combined mode %d\n", arg_ts0_ts1_combined_mode_en); 1095 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1096 } 1097 1098 1099 stack_info.id = 0; 1100 stack_info.flags = 0; 1101 if (arg_ts0_ts1_combined_mode_en) { 1102 stack_info.flags |= BCM_PTP_STACK_TIMESTAMPER_COMBINED_MODE; 1103 } 1104 1105 #if defined(PTP_KEYSTONE_STACK) 1106 stack_info.flags = BCM_PTP_STACK_EXTERNAL_TOP; 1107 stack_info.ext_stack_info = &external; 1108 #endif 1109 parse_arg_eq_done(&pt); 1110 1111 rv = bcm_ptp_stack_create(unit, &stack_info); 1112 1113 if (rv == BCM_E_NONE) { 1114 cur_stack_id = stack_info.id; 1115 PTP_CLI_RESULT_RETURN(CMD_OK); 1116 } else { 1117 cli_out("\nbcm_ptp_stack_create() Error... (FCN RETURN= %d)\n", rv); 1118 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1119 } 1120 1121 #if defined(PTP_KEYSTONE_STACK) 1122 _bcm_ptp_rcpu_configuration_set(unit, cur_stack_id, 0x5000, 0x3150, 0x8100, 1234, 23, 0x5001, switch_mac); 1123 #endif 1124 1125 #ifndef __KERNEL__ 1126 } else if (parse_cmp("Destroy", arg, 0)) { 1127 rv = bcm_ptp_stack_destroy(unit, 0); 1128 if (rv == BCM_E_NONE) { 1129 PTP_CLI_RESULT_RETURN(CMD_OK); 1130 } else { 1131 cli_out("\nbcm_ptp_stack_create() Error... (FCN RETURN= %d)\n", rv); 1132 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1133 } 1134 } else if (parse_cmp("Performance", arg, 0)) { 1135 PTP_IF_ERROR_RETURN(_bcm_ptp_show_system_info(unit, 0, 0)); /* Fixed at stack_id = 0 for now */ 1136 PTP_CLI_RESULT_RETURN(CMD_OK); 1137 #endif 1138 } else { 1139 PTP_CLI_RESULT_RETURN(CMD_USAGE); 1140 } 1141 } 1142 1143 1144 /* PTP Clock */ 1145 #define PTP_CLOCK_USAGE \ 1146 "PTP Clock <SubCommand> [...]\n" \ 1147 "\t PTP Clock Create NumPorts=<num_ports> ID=<clock_id> P1=<priority1>\n" \ 1148 "\t SlaveOnly=<y/N> OneWay=<y/N> TELecom=<y/N>\n" \ 1149 "\t DELayREQuestALT=<y/N> TRaceability=<y/N>\n" \ 1150 "\t PROFile=<0=8265.1, 1=8275.1, 2=8275.2> OffsetScaledLogVar=<> P2=<> HoldoverInspecTime=<sec>\n"\ 1151 "\t PTP Clock Set TRACEability=<NONE|FREQ|TIME|FREQ-TIME|NO-OVERRIDE>\n" \ 1152 "\t PTP Clock Set PKTflags=<SYNC-UNCERTAIN>\n" \ 1153 "\t PTP Clock Show\n" 1154 1155 STATIC cmd_result_t 1156 cmd_ptp_clock(int unit, args_t *a) 1157 { 1158 parse_table_t pt; 1159 char * arg; 1160 1161 int invalid_value = 0x7fffffff; 1162 1163 int rv = BCM_E_NONE; 1164 int num_ports; 1165 int priority1 = PTP_CLOCK_PRESETS_PRIORITY1_DEFAULT; 1166 int arg_slaveOnly = 0; 1167 int arg_oneWay = 0; 1168 int arg_telecomProfile = 0; 1169 int arg_delreqAlt = 0; 1170 int arg_syncOAM = 0; 1171 int arg_domain = -1; 1172 int arg_max_unicast_masters = -1; 1173 int arg_max_acceptable_masters = -1; 1174 int arg_max_unicast_slaves = -1; 1175 int arg_max_multicast_slave_stats = -1; 1176 int arg_traceability = -1; 1177 int arg_profile = 0; 1178 int arg_local_priority = 128; 1179 int arg_max_steps_removed= 255; 1180 int arg_offscal_logvar = -1; 1181 int arg_holdover_inspec_time = 0; 1182 int priority2 = -1; 1183 1184 bcm_ptp_clock_identity_t clock_id; 1185 char *clock_string; 1186 int clock_id_byte = 0; 1187 char *token; 1188 char *rem; 1189 char *tokstr = NULL; 1190 bcm_ptp_trace_t traceability; 1191 int configured = 0; 1192 1193 char *arg_trace_str[6] = {"NONE", "FREQ", "TIME", "FREQ-TIME", "NO-OVERRIDE", 0}; 1194 int arg_trace_index = invalid_value; 1195 1196 char *arg_pktflags_str[2] = {"SYNC-UNCERTAIN", 0}; 1197 int arg_pktflags_index = invalid_value; 1198 1199 arg = ARG_GET(a); 1200 if (!arg) { 1201 PTP_CLI_RESULT_RETURN(CMD_USAGE); 1202 } 1203 if (parse_cmp("Create", arg, 0)) { 1204 bcm_ptp_clock_info_t clock_info = {0, 0, {1,2,3,4,5,6,7,8}, bcmPTPClockTypeBoundary, 2, 1205 248, 0, 1, 128, 64, 0, 0, 0, 1, 1206 PTP_CLOCK_PRESETS_ANNOUNCE_RECEIPT_TIMEOUT_MINIMUM, 1207 PTP_CLOCK_PRESETS_ANNOUNCE_RECEIPT_TIMEOUT_DEFAULT, 1208 PTP_CLOCK_PRESETS_ANNOUNCE_RECEIPT_TIMEOUT_MAXIMUM, 1209 PTP_CLOCK_PRESETS_LOG_ANNOUNCE_INTERVAL_MINIMUM, 1210 PTP_CLOCK_PRESETS_LOG_ANNOUNCE_INTERVAL_DEFAULT, 1211 PTP_CLOCK_PRESETS_LOG_ANNOUNCE_INTERVAL_MAXIMUM, 1212 PTP_CLOCK_PRESETS_LOG_SYNC_INTERVAL_MINIMUM, 1213 PTP_CLOCK_PRESETS_LOG_SYNC_INTERVAL_DEFAULT, 1214 PTP_CLOCK_PRESETS_LOG_SYNC_INTERVAL_MAXIMUM, 1215 PTP_CLOCK_PRESETS_LOG_MIN_DELAY_REQ_INTERVAL_MINIMUM, 1216 PTP_CLOCK_PRESETS_LOG_MIN_DELAY_REQ_INTERVAL_DEFAULT, 1217 PTP_CLOCK_PRESETS_LOG_MIN_DELAY_REQ_INTERVAL_MAXIMUM, 1218 PTP_CLOCK_PRESETS_DOMAIN_NUMBER_MINIMUM, 1219 PTP_CLOCK_PRESETS_DOMAIN_NUMBER_DEFAULT, 1220 PTP_CLOCK_PRESETS_DOMAIN_NUMBER_MAXIMUM, 1221 PTP_CLOCK_PRESETS_PRIORITY1_MINIMUM, 1222 PTP_CLOCK_PRESETS_PRIORITY1_DEFAULT, 1223 PTP_CLOCK_PRESETS_PRIORITY1_MAXIMUM, 1224 PTP_CLOCK_PRESETS_PRIORITY2_MINIMUM, 1225 PTP_CLOCK_PRESETS_PRIORITY2_DEFAULT, 1226 PTP_CLOCK_PRESETS_PRIORITY2_MAXIMUM, 1227 0, 128, 1228 PTP_CLOCK_PRESETS_TELECOM_MAX_STEPS_REMOVED_DEFAULT}; 1229 1230 parse_table_init(unit, &pt); 1231 parse_table_add(&pt, "NumPorts", PQ_INT, (void*)1, &num_ports, NULL); 1232 parse_table_add(&pt, "ID", PQ_STRING, (void*)"11:22:33:ff:fe:44:55:66", 1233 &clock_string, NULL); 1234 parse_table_add(&pt, "P1", PQ_INT, (void*)PTP_CLOCK_PRESETS_PRIORITY1_DEFAULT, 1235 &priority1, NULL); 1236 parse_table_add(&pt, "SlaveOnly", PQ_BOOL, (void*)0, &arg_slaveOnly, NULL); 1237 parse_table_add(&pt, "OneWay", PQ_BOOL, (void*)0, &arg_oneWay, NULL); 1238 parse_table_add(&pt, "TELecom", PQ_BOOL, (void*)0, &arg_telecomProfile, NULL); 1239 parse_table_add(&pt, "DELayREQuestALT", PQ_BOOL, (void*)0, &arg_delreqAlt, NULL); 1240 parse_table_add(&pt, "SYNCOAM", PQ_BOOL, (void*)0, &arg_syncOAM, NULL); 1241 parse_table_add(&pt, "DOMain", PQ_INT, (void*)-1, &arg_domain, NULL); 1242 parse_table_add(&pt, "MaxUnicastMasters", PQ_INT, (void*)-1, &arg_max_unicast_masters, NULL); 1243 parse_table_add(&pt, "MaxAcceptableMasters", PQ_INT, (void*)-1, &arg_max_acceptable_masters, NULL); 1244 parse_table_add(&pt, "MaxUnicastSlaves", PQ_INT, (void*)-1, &arg_max_unicast_slaves, NULL); 1245 parse_table_add(&pt, "MaxMulticastSlaveStats", PQ_INT, (void*)-1, &arg_max_multicast_slave_stats, NULL); 1246 parse_table_add(&pt, "TRaceability", PQ_BOOL, (void*)-1, &arg_traceability, NULL); 1247 parse_table_add(&pt, "PROFile", PQ_INT, (void*)0, &arg_profile, NULL); 1248 parse_table_add(&pt, "LocalPriority", PQ_INT, (void*)128, &arg_local_priority, NULL); 1249 parse_table_add(&pt, "MaxStepsRemoved", PQ_INT, (void*)255, &arg_max_steps_removed, NULL); 1250 parse_table_add(&pt, "OffsetScaledLogVar", PQ_INT, (void*)-1, &arg_offscal_logvar, NULL); 1251 parse_table_add(&pt, "HoldoverInspecTime", PQ_INT, (void*)0, &arg_holdover_inspec_time, NULL); 1252 parse_table_add(&pt, "P2", PQ_INT, (void*)-1, &priority2, NULL); 1253 1254 if (parse_arg_eq(a, &pt) < 0) { 1255 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 1256 } 1257 1258 token = sal_strtok_r(clock_string, ":", &tokstr); 1259 while ((token != NULL) && (clock_id_byte < 8)) { 1260 clock_id[clock_id_byte++] = strtol(token, &rem, 16); 1261 token = sal_strtok_r(NULL, ":", &tokstr); 1262 } 1263 if (clock_id_byte != 8) { 1264 cli_out("\nbcm_ptp_clock_create() Error... ID format\n"); 1265 parse_arg_eq_done(&pt); 1266 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1267 } 1268 1269 if (arg_profile >= e_PtpProfType_None) { 1270 cli_out("\n Error in setting profile type %d\n", arg_profile); 1271 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1272 } 1273 if ((1 == arg_telecomProfile) && (e_PtpProfType_8265p1 != arg_profile)) { 1274 /* Clock can either be configured for frequency or phase profile */ 1275 cli_out("\n Conflicting profile types while configuring clock\n"); 1276 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1277 } 1278 cli_out("\n profile type %d\n", arg_profile); 1279 1280 clock_info.num_ports = num_ports; 1281 if (num_ports > 1) { 1282 clock_info.type = bcmPTPClockTypeBoundary; 1283 } else { 1284 clock_info.type = bcmPTPClockTypeOrdinary; 1285 } 1286 1287 memcpy(clock_info.clock_identity, clock_id, sizeof(clock_id)); 1288 clock_info.priority1 = priority1; 1289 clock_info.slaveonly = arg_slaveOnly; 1290 1291 if (e_PtpProfType_8275p1 == arg_profile) { 1292 /* local_priority shall be in the range 1-255 */ 1293 if ((arg_local_priority > 0) && (arg_local_priority < 256)) { 1294 clock_info.local_priority = (uint8)arg_local_priority; 1295 } else { 1296 cli_out("\n Error in setting local priority %d\n", arg_local_priority); 1297 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1298 } 1299 /* max_steps_removed shall be in the range 1-255 */ 1300 if ((arg_max_steps_removed > 0) && (arg_max_steps_removed < 256)) { 1301 clock_info.max_steps_removed = (uint8)arg_max_steps_removed; 1302 } else { 1303 cli_out("\n Error in setting maxStepsRemoved %d\n", arg_max_steps_removed); 1304 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1305 } 1306 } 1307 1308 if (e_PtpProfType_8275p2 == arg_profile) { 1309 /* local_priority shall be in the range 1-255 */ 1310 if ((arg_local_priority > 0) && (arg_local_priority < 256)) { 1311 clock_info.local_priority = (uint8)arg_local_priority; 1312 } else { 1313 cli_out("\n Error in setting local priority %d\n", arg_local_priority); 1314 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1315 } 1316 } 1317 1318 if (e_PtpProfType_8275p1 == arg_profile || e_PtpProfType_8275p2 == arg_profile) { 1319 clock_info.holdover_in_spec_secs = arg_holdover_inspec_time; 1320 } 1321 1322 clock_info.flags = 0; 1323 1324 /* By default: fixed interval delay requests */ 1325 clock_info.flags |= (1u << PTP_CLOCK_FLAGS_FIXED_DELREQ); 1326 1327 if (1 == arg_oneWay) { 1328 clock_info.flags |= (1u << PTP_CLOCK_FLAGS_ONEWAY_BIT); 1329 } 1330 1331 if (1 == arg_delreqAlt) { 1332 clock_info.flags |= (1u << PTP_CLOCK_FLAGS_DELREQ_ALTMASTER_BIT); 1333 } 1334 1335 if (1 == arg_telecomProfile) { 1336 clock_info.flags |= (1u << PTP_CLOCK_FLAGS_TELECOM_PROFILE_BIT); 1337 1338 /* Enforce telecom profile compliant attributes and profile ranges. */ 1339 clock_info.type = bcmPTPClockTypeOrdinary; 1340 clock_info.num_ports = 1; 1341 1342 if (1 == arg_slaveOnly) { 1343 clock_info.clock_class = 255; 1344 } 1345 /* Domain can be overridden below, but telecom has a different default */ 1346 clock_info.domain_number = 1347 PTP_CLOCK_PRESETS_TELECOM_DOMAIN_NUMBER_DEFAULT; 1348 1349 clock_info.log_announce_interval_minimum = 1350 PTP_CLOCK_PRESETS_TELECOM_LOG_ANNOUNCE_INTERVAL_MINIMUM; 1351 clock_info.log_announce_interval_default = 1352 PTP_CLOCK_PRESETS_TELECOM_LOG_ANNOUNCE_INTERVAL_DEFAULT; 1353 clock_info.log_announce_interval_maximum = 1354 PTP_CLOCK_PRESETS_TELECOM_LOG_ANNOUNCE_INTERVAL_MAXIMUM; 1355 1356 clock_info.log_sync_interval_minimum = 1357 PTP_CLOCK_PRESETS_TELECOM_LOG_SYNC_INTERVAL_MINIMUM; 1358 clock_info.log_sync_interval_default = 1359 PTP_CLOCK_PRESETS_TELECOM_LOG_SYNC_INTERVAL_DEFAULT; 1360 clock_info.log_sync_interval_maximum = 1361 PTP_CLOCK_PRESETS_TELECOM_LOG_SYNC_INTERVAL_MAXIMUM; 1362 1363 clock_info.log_min_delay_req_interval_minimum = 1364 PTP_CLOCK_PRESETS_TELECOM_LOG_MIN_DELAY_REQ_INTERVAL_MINIMUM; 1365 clock_info.log_min_delay_req_interval_default = 1366 PTP_CLOCK_PRESETS_TELECOM_LOG_MIN_DELAY_REQ_INTERVAL_DEFAULT; 1367 clock_info.log_min_delay_req_interval_maximum = 1368 PTP_CLOCK_PRESETS_TELECOM_LOG_MIN_DELAY_REQ_INTERVAL_MAXIMUM; 1369 1370 clock_info.domain_number_minimum = 1371 PTP_CLOCK_PRESETS_TELECOM_DOMAIN_NUMBER_MINIMUM; 1372 clock_info.domain_number_default = 1373 PTP_CLOCK_PRESETS_TELECOM_DOMAIN_NUMBER_DEFAULT; 1374 clock_info.domain_number_maximum = 1375 PTP_CLOCK_PRESETS_TELECOM_DOMAIN_NUMBER_MAXIMUM; 1376 } 1377 1378 if (arg_syncOAM) { 1379 clock_info.flags |= (1u << PTP_CLOCK_FLAGS_SYNCOAM_BIT); 1380 } 1381 1382 if (arg_profile) { 1383 /* Bits#8-11:i identifies the profile type to configure the clock 1384 0: Frequency profile (8265.1) : handled earlier in TELecom arg 1385 1: Phase profile (8275.1) 1386 */ 1387 clock_info.flags |= ((arg_profile & 0x0F) << PTP_CLOCK_FLAGS_PROFILE_TYPE_START_BIT); 1388 /* parameters as required by the 8275.1 telecom phase profile */ 1389 1390 if ( 0x01 == (arg_profile & 0x0F) ) { 1391 /* Domain can be overridden below, but telecom profile for phase has a different default */ 1392 clock_info.domain_number = PTP_CLOCK_PRESETS_TELECOM_PHASE_DOMAIN_NUMBER_DEFAULT; 1393 1394 clock_info.log_announce_interval_minimum = 1395 PTP_CLOCK_PRESETS_TELECOM_LOG_ANNOUNCE_INTERVAL_MINIMUM; 1396 clock_info.log_announce_interval_default = 1397 PTP_CLOCK_PRESETS_TELECOM_PHASE_LOG_ANNOUNCE_INTERVAL_DEFAULT; 1398 clock_info.log_announce_interval_maximum = 1399 PTP_CLOCK_PRESETS_TELECOM_LOG_ANNOUNCE_INTERVAL_MAXIMUM; 1400 1401 clock_info.log_sync_interval_minimum = 1402 PTP_CLOCK_PRESETS_TELECOM_LOG_SYNC_INTERVAL_MINIMUM; 1403 clock_info.log_sync_interval_default = 1404 PTP_CLOCK_PRESETS_TELECOM_PHASE_LOG_SYNC_INTERVAL_DEFAULT; 1405 clock_info.log_sync_interval_maximum = 1406 PTP_CLOCK_PRESETS_TELECOM_LOG_SYNC_INTERVAL_MAXIMUM; 1407 1408 clock_info.log_min_delay_req_interval_minimum = 1409 PTP_CLOCK_PRESETS_TELECOM_LOG_MIN_DELAY_REQ_INTERVAL_MINIMUM; 1410 clock_info.log_min_delay_req_interval_default = 1411 PTP_CLOCK_PRESETS_TELECOM_PHASE_LOG_MIN_DELAY_REQ_INTERVAL_DEFAULT; 1412 clock_info.log_min_delay_req_interval_maximum = 1413 PTP_CLOCK_PRESETS_TELECOM_LOG_MIN_DELAY_REQ_INTERVAL_MAXIMUM; 1414 1415 clock_info.domain_number_minimum = 1416 PTP_CLOCK_PRESETS_TELECOM_PHASE_DOMAIN_NUMBER_MINIMUM; 1417 clock_info.domain_number_default = 1418 PTP_CLOCK_PRESETS_TELECOM_PHASE_DOMAIN_NUMBER_DEFAULT; 1419 clock_info.domain_number_maximum = 1420 PTP_CLOCK_PRESETS_TELECOM_PHASE_DOMAIN_NUMBER_MAXIMUM; 1421 1422 if (clock_info.slaveonly) { 1423 /* For TSC, priority2 shall be 255 */ 1424 clock_info.priority2 = PTP_CLOCK_PRESETS_TELECOM_PHASE_PRIORITY2_TSC_DEFAULT; 1425 } 1426 1427 if (clock_info.type == bcmPTPClockTypeBoundary) { 1428 clock_info.priority2 = PTP_CLOCK_PRESETS_TELECOM_PHASE_PRIORITY2_TBC_DEFAULT; 1429 /* For G.8275.1, user can configure offsetScaledLogVariance as per below. 1430 defaultDS.clockQuality.offsetScaledLogVariance: 1431 - 0x4E5D for a T-GM connected to a PRTC in locked-mode (i.e. PRTC traceable to GNSS) 1432 - 0xFFFF for a T-GM not connected to a PRTC in locked-mode 1433 - 0xFFFF for a T-BC, all the time */ 1434 clock_info.scaled_log_variance = 0xFFFF; 1435 } 1436 } else if ( 0x02 == (arg_profile & 0x0F) ) { 1437 /* Range Configuration for G.8275.2 Profile based on Table A.1 */ 1438 /* Domain can be overridden below, but telecom profile for phase has a different default */ 1439 clock_info.domain_number_minimum = PTP_CLOCK_PRESETS_G8275P2_DOMAIN_NUMBER_MINIMUM; 1440 clock_info.domain_number_default = PTP_CLOCK_PRESETS_G8275P2_DOMAIN_NUMBER_DEFAULT; 1441 clock_info.domain_number_maximum = PTP_CLOCK_PRESETS_G8275P2_DOMAIN_NUMBER_MAXIMUM; 1442 1443 clock_info.priority1_minimum = PTP_CLOCK_PRESETS_G8275P2_PRIORITY1_MINIMUM; 1444 clock_info.priority1_default = PTP_CLOCK_PRESETS_G8275P2_PRIORITY1_DEFAULT; 1445 clock_info.priority1_maximum = PTP_CLOCK_PRESETS_G8275P2_PRIORITY1_MAXIMUM; 1446 1447 clock_info.priority2_minimum = PTP_CLOCK_PRESETS_G8275P2_PRIORITY2_MINIMUM; 1448 clock_info.priority2_default = PTP_CLOCK_PRESETS_G8275P2_PRIORITY2_DEFAULT; 1449 clock_info.priority2_maximum = PTP_CLOCK_PRESETS_G8275P2_PRIORITY2_MAXIMUM; 1450 1451 /* Range Configuration for G.8275.2 Profile based on Section A.3.4 */ 1452 clock_info.log_announce_interval_minimum = 1453 PTP_CLOCK_PRESETS_G8275P2_LOG_ANNOUNCE_INTERVAL_MINIMUM; 1454 clock_info.log_announce_interval_default = 1455 PTP_CLOCK_PRESETS_G8275P2_LOG_ANNOUNCE_INTERVAL_DEFAULT; 1456 clock_info.log_announce_interval_maximum = 1457 PTP_CLOCK_PRESETS_G8275P2_LOG_ANNOUNCE_INTERVAL_MAXIMUM; 1458 1459 clock_info.log_sync_interval_minimum = 1460 PTP_CLOCK_PRESETS_G8275P2_LOG_SYNC_INTERVAL_MINIMUM; 1461 clock_info.log_sync_interval_default = 1462 PTP_CLOCK_PRESETS_G8275P2_LOG_SYNC_INTERVAL_DEFAULT; 1463 clock_info.log_sync_interval_maximum = 1464 PTP_CLOCK_PRESETS_G8275P2_LOG_SYNC_INTERVAL_MAXIMUM; 1465 1466 clock_info.log_min_delay_req_interval_minimum = 1467 PTP_CLOCK_PRESETS_G8275P2_LOG_MIN_DELAY_REQ_INTERVAL_MINIMUM; 1468 clock_info.log_min_delay_req_interval_default = 1469 PTP_CLOCK_PRESETS_G8275P2_LOG_MIN_DELAY_REQ_INTERVAL_DEFAULT; 1470 clock_info.log_min_delay_req_interval_maximum = 1471 PTP_CLOCK_PRESETS_G8275P2_LOG_MIN_DELAY_REQ_INTERVAL_MAXIMUM; 1472 1473 /* Override values needed for G8275P2 Profile as per A.1 */ 1474 if (1 == arg_slaveOnly) { 1475 clock_info.clock_class = 255; 1476 } else { 1477 clock_info.clock_class = 248; 1478 } 1479 1480 clock_info.domain_number = PTP_CLOCK_PRESETS_G8275P2_DOMAIN_NUMBER_DEFAULT; 1481 clock_info.priority1 = PTP_CLOCK_PRESETS_G8275P2_PRIORITY1_DEFAULT; 1482 clock_info.priority2 = PTP_CLOCK_PRESETS_G8275P2_PRIORITY2_DEFAULT; 1483 /* 1484 * For G.8275.1, user can configure offsetScaledLogVariance as per below. 1485 * defaultDS.clockQuality.offsetScaledLogVariance: 1486 * 0x4B32 for a T-GM connected to an ePRTC in locked-mode 1487 * 0x4E5D for a T-GM connected to a PRTC in locked-mode 1488 * 0xFFFF for a T-GM not connected to a PRTC in locked-mode 1489 * 0xFFFF for a T-BC-P not connected to a GNSS in locked mode on a virtual PTP port 1490 */ 1491 clock_info.scaled_log_variance = 0xFFFF; 1492 clock_info.announce_receipt_timeout_default = 1493 PTP_CLOCK_PRESETS_G8275P2_ANNOUNCE_RECEIPT_TIMEOUT_DEFAULT; 1494 1495 } 1496 } 1497 1498 parse_arg_eq_done(&pt); 1499 1500 if (priority2 >= 0 ) { 1501 /* p2 is explicitly configured - override */ 1502 clock_info.priority2 = priority2; 1503 } 1504 if (arg_offscal_logvar >= 0) { 1505 /* To work with IXIA, offset scaled log var needs to be set to 0 */ 1506 clock_info.scaled_log_variance = (uint16)arg_offscal_logvar; 1507 } 1508 1509 if (arg_domain >= 0) { 1510 clock_info.domain_number = arg_domain; 1511 } 1512 1513 if (arg_max_unicast_masters >= 0) { 1514 _bcm_ptp_set_max_unicast_masters(unit, cur_stack_id, arg_max_unicast_masters); 1515 } 1516 1517 if (arg_max_acceptable_masters >= 0) { 1518 _bcm_ptp_set_max_acceptable_masters(unit, cur_stack_id, arg_max_acceptable_masters); 1519 } 1520 1521 if (arg_max_unicast_slaves >= 0) { 1522 _bcm_ptp_set_max_unicast_slaves(unit, cur_stack_id, arg_max_unicast_slaves); 1523 } 1524 1525 if (arg_max_multicast_slave_stats >= 0) { 1526 _bcm_ptp_set_max_multicast_slave_stats(unit, cur_stack_id, arg_max_multicast_slave_stats); 1527 } 1528 1529 rv = bcm_ptp_clock_create(unit, cur_stack_id, &clock_info); 1530 if (rv == BCM_E_NONE) { 1531 cur_clock_num = clock_info.clock_num; 1532 1533 if (1 == arg_traceability) { 1534 traceability.frequency_traceable = 1; 1535 traceability.time_traceable = 1; 1536 configured = 1; 1537 } else if (0 == arg_traceability) { 1538 traceability.frequency_traceable = 0; 1539 traceability.time_traceable = 0; 1540 configured = 1; 1541 } 1542 1543 if (configured == 1 && e_PtpProfType_8275p2 != arg_profile) { 1544 rv = bcm_ptp_clock_traceability_set(unit, cur_stack_id, cur_clock_num, &traceability); 1545 if (rv != BCM_E_NONE) { 1546 cli_out("\nbcm_ptp_clock_traceability_set() Error... (FCN RETURN= %d)\n", rv); 1547 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1548 } 1549 } 1550 if (e_PtpProfType_8275p2 == arg_profile) { 1551 rv = bcm_ptp_unicast_request_duration_min_set(unit, cur_stack_id, cur_clock_num, 0, 1552 BCM_PTP_SIGNAL_G8275P2_REQUEST_UC_MINIMUM_DURATION_SEC); 1553 if (rv != BCM_E_NONE) { 1554 cli_out("\nbcm_ptp_unicast_request_duration_min_set() Error... (FCN RETURN= %d)\n", rv); 1555 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1556 } 1557 rv = bcm_ptp_unicast_request_duration_max_set(unit, cur_stack_id, cur_clock_num, 0, 1558 BCM_PTP_SIGNAL_G8275P2_REQUEST_UC_MAXIMUM_DURATION_SEC); 1559 if (rv != BCM_E_NONE) { 1560 cli_out("\nbcm_ptp_unicast_request_duration_max_set() Error... (FCN RETURN= %d)\n", rv); 1561 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1562 } 1563 rv = bcm_ptp_unicast_request_duration_set(unit, cur_stack_id, cur_clock_num, 0, 1564 BCM_PTP_SIGNAL_G8275P2_REQUEST_UC_DEFAULT_DURATION_SEC); 1565 if (rv != BCM_E_NONE) { 1566 cli_out("\nbcm_ptp_unicast_request_duration_set() Error... (FCN RETURN= %d)\n", rv); 1567 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1568 } 1569 } 1570 PTP_CLI_RESULT_RETURN(CMD_OK); 1571 } 1572 else { 1573 cli_out("\nbcm_ptp_clock_create() Error... (FCN RETURN= %d)\n", rv); 1574 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1575 } 1576 } else if (parse_cmp(arg, "Set", 0)) { 1577 parse_table_init(unit, &pt); 1578 parse_table_add(&pt, "TRACEability", PQ_MULTI | PQ_DFL, 0, &arg_trace_index, arg_trace_str); 1579 parse_table_add(&pt, "PKTflags", PQ_MULTI | PQ_DFL, 0, &arg_pktflags_index, arg_pktflags_str); 1580 1581 if (parse_arg_eq(a, &pt) < 0) { 1582 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 1583 } 1584 parse_arg_eq_done(&pt); 1585 1586 if (arg_trace_index != invalid_value) { 1587 switch (arg_trace_index) { 1588 case 0: 1589 /* NONE: Frequency-Traceable FALSE, Time-Traceable FALSE */ 1590 traceability.frequency_traceable = 0; 1591 traceability.time_traceable = 0; 1592 break; 1593 case 1: 1594 /* FREQ: Frequency-Traceable TRUE , Time-Traceable FALSE */ 1595 traceability.frequency_traceable = 1; 1596 traceability.time_traceable = 0; 1597 break; 1598 case 2: 1599 /* TIME: Frequency-Traceable FALSE, Time-Traceable TRUE */ 1600 traceability.frequency_traceable = 0; 1601 traceability.time_traceable = 1; 1602 break; 1603 case 3: 1604 /* FREQ+TIME: Frequency-Traceable TRUE , Time-Traceable TRUE */ 1605 traceability.frequency_traceable = 1; 1606 traceability.time_traceable = 1; 1607 break; 1608 case 4: 1609 /* No OverRide, Follow the GM Traceability option */ 1610 traceability.frequency_traceable = BCM_PTP_TRACEABILITY_NO_OVERRIDE; 1611 traceability.time_traceable = BCM_PTP_TRACEABILITY_NO_OVERRIDE; 1612 break; 1613 default: 1614 cli_out("PTP CLOCK SET ... : Invalid traceability configuration.\n"); 1615 PTP_CLI_RESULT_RETURN(CMD_USAGE); 1616 } 1617 1618 PTP_IF_ERROR_RETURN(bcm_ptp_clock_traceability_set(unit, cur_stack_id, cur_clock_num, &traceability)); 1619 } 1620 1621 if (arg_pktflags_index != invalid_value) { 1622 switch (arg_pktflags_index) { 1623 case 0: 1624 /* SYNC-UNCERTAIN */ 1625 { 1626 uint32 mask=0; 1627 uint32 value=0; 1628 1629 mask |= (1 << BCM_PTP_PKT_FLAG_SYNC_UNCERTAIN); 1630 value |= (1 << BCM_PTP_PKT_FLAG_SYNC_UNCERTAIN); 1631 bcm_ptp_pkt_flags_override_set(0,0,0, mask, value); 1632 } 1633 1634 break; 1635 default: 1636 cli_out("PTP CLOCK SET ... : Invalid packet flags configuration.\n"); 1637 PTP_CLI_RESULT_RETURN(CMD_USAGE); 1638 } 1639 1640 } 1641 1642 1643 PTP_CLI_RESULT_RETURN(CMD_OK); 1644 1645 } else if (parse_cmp(arg, "Show", 0)) { 1646 return ptp_show_clock(unit, cur_stack_id, cur_clock_num); 1647 } else if (parse_cmp(arg, "Peers", 0)) { 1648 return ptp_show_peers(unit, cur_stack_id, cur_clock_num); 1649 } else { 1650 PTP_CLI_RESULT_RETURN(CMD_USAGE); 1651 } 1652 } 1653 1654 1655 /* PTP Port */ 1656 #define PTP_PORT_USAGE \ 1657 "PTP Port <SubCommand> [port_num] [...]\n\t" \ 1658 " PTP Port Configure [port_num] MAC=<macaddr> IP=<ipaddr> IPv6=<ip6addr> MultiCast=<Y/n> WILDcard=<y/N>\n\t" \ 1659 " Prio=<prio> logAnnounceInterval=<intv> logSyncInterval=<intv> Vlan=<tag>\n\t" \ 1660 " logDelayrequestInterval=<intv> TimestampMechanism=<ToP|RCPU|PHY|Unimac32|Unimac48>\n\t" \ 1661 " PTP Port Show [port_num]\n" \ 1662 " PTP Port Dropcounter [port_num] Config ENable=<y/N>\n" \ 1663 " PTP Port Dropcounter [port_num] Show\n" 1664 1665 STATIC cmd_result_t 1666 cmd_ptp_port(int unit, args_t *a) 1667 { 1668 int rv; 1669 char * arg; 1670 uint8 l2_multicast_mac[6] = {0x01, 0x1B, 0x19, 0x00, 0x00, 0x00}; 1671 uint8 l2_multicast_pdelay_mac[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e}; 1672 1673 uint8 ipv4_multicast_mac[6] = {0x01, 0x00, 0x5e, 0x00, 0x01, 0x81}; 1674 uint8 ipv4_multicast_pdelay_mac[6] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x6b}; 1675 1676 uint8 ipv6_multicast_mac[6] = {0x33, 0x33, 0x00, 0x00, 0x01, 0x81}; 1677 uint8 ipv6_multicast_pdelay_mac[6] = {0x33, 0x33, 0x00, 0x00, 0x00, 0x6b}; 1678 1679 1680 arg = ARG_GET(a); 1681 if (!arg) { 1682 PTP_CLI_RESULT_RETURN(CMD_USAGE); 1683 } 1684 1685 if (parse_cmp("Configure", arg, 0)) { 1686 bcm_ptp_clock_info_t clock_info; 1687 int port = 0; 1688 int vlan = 1; 1689 int prio = 0; 1690 int16 vlantag; 1691 bcm_ip_t ip; 1692 bcm_ip6_t ip6 = {0}; 1693 uint8 blank[16] = {0}; 1694 int profile_type; 1695 int multicast = 1, wildcard = 0; 1696 int port_type=1, local_prio=128; 1697 1698 bcm_ptp_clock_port_info_t port_info = {{bcmPTPUDPIPv4, {192,168,0,55}}, 1699 {0, 0, 0, 0, 0, 0}, 1700 0, {0}, 0, {0}, 1701 1, bcmPTPPortTypeStandard, 1702 3, 1, -5, -5, 1703 bcmPTPDelayMechanismEnd2End, bcmPTPMac32CorrectionTimestamps, 1704 1, 0, 0xffffffff, 1, 128 1705 }; 1706 1707 char *arg_timestamp_mechanism = 0; 1708 1709 int vp_clock_class = 0; 1710 int vp_clock_accur = 0; 1711 int vp_scaled_var = 0; 1712 int vp_steps_rem = 0; 1713 int vp_gm_priority2 = 0; 1714 int vp_one_pps_in_gpio=0; 1715 char * blank_str = ""; 1716 char *format= 0; 1717 const char *fmt_str= 0, *mask_str=0; 1718 char *custom_fmt_str = 0, *custom_mask_str = 0; 1719 int tod_offset_sec=0; 1720 int tod_offset_ns=0; 1721 int ethertype=0; 1722 int uartNum; 1723 uint32 baudRate; 1724 1725 /* NMEA ZDA "$GPZDA,HHMMSS.00,DD,MM,YYYY,zz,zz*CC"*/ 1726 const char * nmea_mask_str = " x xxxx x x xxxxxxxxx"; 1727 const char * nmea_fmt_str = "$GPZDA %2H%2M%2S %d %m %Y"; 1728 1729 /* ISO "YYYY-MM-DDTHH:MM:SS.000Z" "*/ 1730 const char * iso_mask_str = " xxxxx"; 1731 const char * iso_fmt_str = "%Y-%m-%dT%H:%M:%S"; 1732 1733 /* NTP " YY JJ HH:MM:SS.000 S" */ 1734 const char * ntp_mask_str = "xx x x xxxx"; 1735 const char * ntp_fmt_str = " %y %j %H %M %S "; 1736 1737 1738 parse_table_t pt; 1739 parse_table_init(unit, &pt); 1740 parse_table_add(&pt, "MultiCast", PQ_BOOL, (void*)1, &multicast, NULL); 1741 parse_table_add(&pt, "WILDcard", PQ_BOOL, (void*)0, &wildcard, NULL); 1742 parse_table_add(&pt, "Vlan", PQ_INT, (void*)1, &vlan, NULL); 1743 parse_table_add(&pt, "Prio", PQ_INT, (void*)0, &prio, NULL); 1744 parse_table_add(&pt, "MAC", PQ_MAC | PQ_DFL, (void*)0, port_info.mac, NULL); 1745 parse_table_add(&pt, "IP", PQ_IP, (void*)0, &ip, NULL); 1746 parse_table_add(&pt, "IPv6", PQ_IP6 | PQ_DFL, (void*)0, &ip6, NULL); 1747 parse_table_add(&pt, "logAnnounceInterval", PQ_INT | PQ_DFL, (void*)0, &port_info.log_announce_interval, NULL); 1748 parse_table_add(&pt, "logSyncInterval", PQ_INT | PQ_DFL, (void*)0, &port_info.log_sync_interval, NULL); 1749 parse_table_add(&pt, "logDelayrequestInterval", PQ_INT | PQ_DFL, (void*)0, &port_info.log_min_delay_req_interval, NULL); 1750 parse_table_add(&pt, "TimestampMechanism", PQ_STRING, (void*)"", &arg_timestamp_mechanism, NULL); 1751 parse_table_add(&pt, "PortType", PQ_INT, (void*)1, &port_type, NULL); 1752 parse_table_add(&pt, "LocalPriority", PQ_INT, (void*)128, &local_prio, NULL); 1753 parse_table_add(&pt, "FormatType", PQ_STRING, blank_str, &format, NULL); 1754 parse_table_add(&pt, "CustomFormatStr", PQ_STRING, blank_str, &custom_fmt_str, NULL); 1755 parse_table_add(&pt, "CustomMaskStr", PQ_STRING, blank_str, &custom_mask_str, NULL); 1756 parse_table_add(&pt, "EtherType", PQ_INT, (void*)BCM_TOD_ETHERTYPE, ðertype, NULL); 1757 parse_table_add(&pt, "OffsetSec", PQ_INT, (void*)0, &tod_offset_sec, NULL); 1758 parse_table_add(&pt, "OffsetNS", PQ_INT, (void*)0, &tod_offset_ns, NULL); 1759 parse_table_add(&pt, "VirtualPortClockClass", PQ_INT, (void*)0, &vp_clock_class, NULL); 1760 parse_table_add(&pt, "VirtualPortClockAccuracy", PQ_INT, (void*)0, &vp_clock_accur, NULL); 1761 parse_table_add(&pt, "VirtualPortScaledVar", PQ_INT, (void*)0, &vp_scaled_var, NULL); 1762 parse_table_add(&pt, "VirtualPortStepsRemoved", PQ_INT, (void*)0, &vp_steps_rem, NULL); 1763 parse_table_add(&pt, "VirtualPortGmPrio2", PQ_INT, (void*)0, &vp_gm_priority2, NULL); 1764 parse_table_add(&pt, "VirtualPort1PPSIn", PQ_INT, (void*)0, &vp_one_pps_in_gpio, NULL); 1765 if(PTP_UC_FEATURE_CHECK(PTP_VP_TOD_IN_SERIAL)) { 1766 parse_table_add(&pt, "VirtualPortUART", PQ_INT, (void*)-1, &uartNum, NULL); 1767 parse_table_add(&pt, "VirtualPortBaudRate", PQ_INT, (void*)0, &baudRate, NULL); 1768 } 1769 1770 arg = ARG_GET(a); 1771 if (!arg) { 1772 parse_arg_eq_done(&pt); 1773 PTP_CLI_RESULT_RETURN(CMD_USAGE); 1774 } 1775 1776 port = parse_integer(arg); 1777 1778 if (parse_arg_eq(a, &pt) < 0) { 1779 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 1780 } 1781 1782 if (sal_memcmp(port_info.mac, blank, 6) == 0) { 1783 /* no valid MAC was given */ 1784 parse_arg_eq_done(&pt); 1785 PTP_CLI_RESULT_RETURN(CMD_USAGE); 1786 } 1787 1788 1789 vlantag = (int16) (vlan + (prio << 13)); 1790 if (vlantag != 0) 1791 { 1792 port_info.rx_packets_vlan = vlantag; 1793 } 1794 1795 if (ip != 0) { 1796 port_info.port_address.address[0] = (uint8)(ip >> 24); 1797 port_info.port_address.address[1] = (uint8)(ip >> 16); 1798 port_info.port_address.address[2] = (uint8)(ip >> 8); 1799 port_info.port_address.address[3] = (uint8)(ip); 1800 1801 memcpy(port_info.multicast_l2, ipv4_multicast_mac, 6); 1802 memcpy(port_info.multicast_l2 + 6, port_info.mac, 6); 1803 port_info.multicast_l2[12] = 0x81; 1804 port_info.multicast_l2[13] = 0x00; 1805 port_info.multicast_l2[14] = (uint8)(vlantag >> 8); 1806 port_info.multicast_l2[15] = (uint8)(vlantag); 1807 port_info.multicast_l2[16] = 0x08; 1808 port_info.multicast_l2[17] = 0x00; 1809 port_info.multicast_l2_size = 18; 1810 1811 memcpy(port_info.multicast_pdelay_l2, ipv4_multicast_pdelay_mac, 6); 1812 memcpy(port_info.multicast_pdelay_l2 + 6, port_info.mac, 6); 1813 port_info.multicast_pdelay_l2[12] = 0x81; 1814 port_info.multicast_pdelay_l2[13] = 0x00; 1815 port_info.multicast_pdelay_l2[14] = (uint8)(vlantag >> 8); 1816 port_info.multicast_pdelay_l2[15] = (uint8)(vlantag); 1817 port_info.multicast_pdelay_l2[16] = 0x08; 1818 port_info.multicast_pdelay_l2[17] = 0x00; 1819 port_info.multicast_pdelay_l2_size = 18; 1820 1821 } else if (sal_memcmp(ip6, blank, 16) != 0) { 1822 sal_memcpy(port_info.port_address.address, ip6, 16); 1823 port_info.port_address.addr_type = bcmPTPUDPIPv6; 1824 1825 memcpy(port_info.multicast_l2, ipv6_multicast_mac, 6); 1826 memcpy(port_info.multicast_l2 + 6, port_info.mac, 6); 1827 port_info.multicast_l2[12] = 0x81; 1828 port_info.multicast_l2[13] = 0x00; 1829 port_info.multicast_l2[14] = (uint8)(vlantag >> 8); 1830 port_info.multicast_l2[15] = (uint8)(vlantag); 1831 port_info.multicast_l2[16] = 0x86; 1832 port_info.multicast_l2[17] = 0xdd; 1833 port_info.multicast_l2_size = 18; 1834 1835 memcpy(port_info.multicast_pdelay_l2, ipv6_multicast_pdelay_mac, 6); 1836 memcpy(port_info.multicast_pdelay_l2 + 6, port_info.mac, 6); 1837 port_info.multicast_pdelay_l2[12] = 0x81; 1838 port_info.multicast_pdelay_l2[13] = 0x00; 1839 port_info.multicast_pdelay_l2[14] = (uint8)(vlantag >> 8); 1840 port_info.multicast_pdelay_l2[15] = (uint8)(vlantag); 1841 port_info.multicast_pdelay_l2[16] = 0x86; 1842 port_info.multicast_pdelay_l2[17] = 0xdd; 1843 port_info.multicast_pdelay_l2_size = 18; 1844 1845 } else { 1846 sal_memcpy(port_info.port_address.address, port_info.mac, 6); 1847 port_info.port_address.addr_type = bcmPTPIEEE8023; 1848 1849 memcpy(port_info.multicast_l2, l2_multicast_mac, 6); 1850 memcpy(port_info.multicast_l2 + 6, port_info.mac, 6); 1851 port_info.multicast_l2[12] = 0x81; 1852 port_info.multicast_l2[13] = 0x00; 1853 port_info.multicast_l2[14] = (uint8)(vlantag >> 8); 1854 port_info.multicast_l2[15] = (uint8)(vlantag); 1855 port_info.multicast_l2[16] = 0x88; 1856 port_info.multicast_l2[17] = 0xf7; 1857 port_info.multicast_l2_size = 18; 1858 1859 memcpy(port_info.multicast_pdelay_l2, l2_multicast_pdelay_mac, 6); 1860 memcpy(port_info.multicast_pdelay_l2 + 6, port_info.mac, 6); 1861 port_info.multicast_pdelay_l2[12] = 0x81; 1862 port_info.multicast_pdelay_l2[13] = 0x00; 1863 port_info.multicast_pdelay_l2[14] = (uint8)(vlantag >> 8); 1864 port_info.multicast_pdelay_l2[15] = (uint8)(vlantag); 1865 port_info.multicast_pdelay_l2[16] = 0x88; 1866 port_info.multicast_pdelay_l2[17] = 0xf7; 1867 port_info.multicast_pdelay_l2_size = 18; 1868 } 1869 1870 #if defined(PTP_KEYSTONE_STACK) 1871 port_info.rx_timestamp_mechanism = bcmPTPToPTimestamps; 1872 #else 1873 port_info.rx_timestamp_mechanism = bcmPTPMac32CorrectionTimestamps; 1874 #endif 1875 if (arg_timestamp_mechanism) { 1876 if (parse_cmp("ToP", arg_timestamp_mechanism, 0)) { 1877 port_info.rx_timestamp_mechanism = bcmPTPToPTimestamps; 1878 } else if (parse_cmp("RCPU", arg_timestamp_mechanism, 0)) { 1879 port_info.rx_timestamp_mechanism = bcmPTPRCPUTimestamps; 1880 } else if (parse_cmp("PHY", arg_timestamp_mechanism, 0)) { 1881 port_info.rx_timestamp_mechanism = bcmPTPPhyCorrectionTimestamps; 1882 } else if (parse_cmp("Unimac32", arg_timestamp_mechanism, 0)) { 1883 port_info.rx_timestamp_mechanism = bcmPTPMac32CorrectionTimestamps; 1884 } else if (parse_cmp("Unimac48", arg_timestamp_mechanism, 0)) { 1885 port_info.rx_timestamp_mechanism = bcmPTPMac48CorrectionTimestamps; 1886 if (SOC_IS_TRIDENT2PLUS(unit)) { 1887 cli_out("\n TD2PLUS : PTP application do not support 48 bit time-stamping \n"); 1888 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1889 } 1890 } 1891 } 1892 1893 port_info.multicast_tx_enable = multicast ? 1 : 0; 1894 1895 port_info.rx_packets_criteria_mask = 0; 1896 1897 1898 if (multicast) { 1899 port_info.rx_packets_criteria_mask |= BCM_PTP_RXMAP_ACCEPT_MULTICAST; 1900 } 1901 1902 if (wildcard) { 1903 port_info.rx_packets_criteria_mask |= BCM_PTP_RXMAP_MATCH_ANY_ADDR; 1904 } 1905 1906 if (port_info.rx_packets_vlan != 1) { 1907 #if defined(PTP_KEYSTONE_STACK) 1908 /* TPID 0x8100 is by default configured as Inner TPID for Keystone */ 1909 port_info.rx_packets_criteria_mask |= BCM_PTP_RXMAP_MATCH_INNER_VLAN; 1910 #else 1911 port_info.rx_packets_criteria_mask |= BCM_PTP_RXMAP_MATCH_OUTER_VLAN; 1912 #endif 1913 } 1914 1915 if (BCM_FAILURE(rv = bcm_ptp_clock_get(unit,cur_stack_id,cur_clock_num,&clock_info))) { 1916 cli_out("\nbcm_ptp_clock_get() Error... (FCN RETURN= %d)\n", rv); 1917 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1918 } 1919 1920 profile_type = ((clock_info.flags >> 8) & 0x0F); 1921 if (profile_type == e_PtpProfType_8275p2) { 1922 port_info.announce_receipt_timeout = 3; 1923 } 1924 1925 port_info.port_type = (bcm_ptp_port_type_t)port_type; 1926 1927 /* local_priority shall be in the range 1-255 */ 1928 if ((local_prio > 0) && (local_prio < 256)) { 1929 port_info.local_priority = (uint8)local_prio; 1930 } else { 1931 cli_out("\n Error in setting local priority %d\n", local_prio); 1932 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1933 } 1934 1935 if (port_type == bcmPTPPortTypeVirtual || 1936 port_type == bcmPTPPortTypeCustomizedVirtual) { 1937 1938 port_info.vport_info.clock_class = (uint8) vp_clock_class; 1939 port_info.vport_info.clock_accuracy = (bcm_ptp_clock_accuracy_t)vp_clock_accur; 1940 port_info.vport_info.offset_scaled_log_variance = (uint16) vp_scaled_var; 1941 port_info.vport_info.steps_removed = (uint16) vp_steps_rem; 1942 port_info.vport_info.GM_prio2 = (uint8) vp_gm_priority2; 1943 port_info.vport_info.onepps_in_gpio = (uint8) vp_one_pps_in_gpio; 1944 if(PTP_UC_FEATURE_CHECK(PTP_VP_TOD_IN_SERIAL)) { 1945 switch (uartNum) { 1946 case -1: 1947 port_info.vport_info.tod_source = bcmPTPTODSourceEthernet; 1948 break; 1949 case 0: 1950 port_info.vport_info.tod_source = bcmPTPTODSourceSerial; 1951 break; 1952 case 1: 1953 port_info.vport_info.tod_source = bcmPTPTODSourceSerial1; 1954 break; 1955 case 2: 1956 port_info.vport_info.tod_source = bcmPTPTODSourceSerial2; 1957 break; 1958 case 3: 1959 port_info.vport_info.tod_source = bcmPTPTODSourceSerial3; 1960 break; 1961 default: 1962 port_info.vport_info.tod_source = bcmPTPTODSourceSerial; 1963 break; 1964 } 1965 port_info.vport_info.tod_baud_rate = (uint32) baudRate; 1966 } 1967 port_info.vport_info.ether_type = (uint16)ethertype; 1968 port_info.vport_info.tod_offset_sec = tod_offset_sec; 1969 port_info.vport_info.tod_offset_ns = tod_offset_ns; 1970 1971 if (parse_cmp("", format, 0)) { 1972 cli_out("\n ToD Format needs to be specified for virtual port %s", format); 1973 PTP_CLI_RESULT_RETURN(CMD_FAIL); 1974 } else { 1975 cli_out("\n ToD Format specified for virtual port [%s]", format); 1976 } 1977 1978 if (parse_cmp("NMEAzda", format, 0)) { 1979 fmt_str = nmea_fmt_str; 1980 mask_str = nmea_mask_str; 1981 } else if (parse_cmp("ISO8601", format, 0)) { 1982 fmt_str = iso_fmt_str; 1983 mask_str = iso_mask_str; 1984 } else if (parse_cmp("NTP", format, 0)) { 1985 fmt_str = ntp_fmt_str; 1986 mask_str = ntp_mask_str; 1987 } else if (parse_cmp("CUSTom", format, 0)) { 1988 fmt_str = custom_fmt_str; 1989 mask_str = custom_mask_str; 1990 } 1991 if (fmt_str) { 1992 cli_out("\n fmt_str[%s] \n", fmt_str); 1993 port_info.vport_info.format = bcmPTPTODFormatString; 1994 sal_strncpy((char *)port_info.vport_info.format_str, 1995 fmt_str, BCM_PTP_MAX_TOD_FORMAT_STRING - 1); 1996 sal_strncpy((char *)port_info.vport_info.mask_str, 1997 mask_str, BCM_PTP_MAX_TOD_FORMAT_STRING - 1); 1998 } else if (parse_cmp("UBlox", format, 0)) { 1999 port_info.vport_info.format = bcmPTPTODFormatUBlox; 2000 } else if (parse_cmp("ChinaMobile", format, 0)) { 2001 port_info.vport_info.format = bcmPTPTODFormatChinaTcom; /* China Mobile/Telecom use same enumerator. */ 2002 sal_sprintf((char *)port_info.vport_info.format_str, "CM"); 2003 } else if (parse_cmp("ChinaTelecom", format, 0)) { 2004 port_info.vport_info.format = bcmPTPTODFormatChinaTcom; /* China Mobile/Telecom use same enumerator. */ 2005 sal_sprintf((char *)port_info.vport_info.format_str, "CT"); 2006 } else if (parse_cmp("G8271", format, 0)) { 2007 port_info.vport_info.format = bcmPTPTODFormatG8271; 2008 sal_sprintf((char *)port_info.vport_info.format_str, "CM"); /* String is same as ChinaMobile */ 2009 } else if (parse_cmp("BCM", format, 0)) { 2010 /* BCMTS is to be used only with redundant setup on stand-by TC. Hence, not considered */ 2011 port_info.vport_info.format = bcmPTPTODFormatBCM; 2012 } else { 2013 cli_out("\n ToD Format[%s] specified for virtual port is invalid ", format); 2014 } 2015 } 2016 parse_arg_eq_done(&pt); 2017 2018 rv = bcm_ptp_clock_port_configure(unit, cur_stack_id, cur_clock_num, port, &port_info); 2019 2020 cur_port_num = port; 2021 2022 if (rv) { 2023 if (rv == BCM_E_PARAM) 2024 cli_out("Failed: invalid parameters\n"); 2025 PTP_CLI_RESULT_RETURN(CMD_FAIL); 2026 } else { 2027 PTP_CLI_RESULT_RETURN(CMD_OK); 2028 } 2029 2030 } else if (parse_cmp(arg, "Show", 0)) { 2031 int port = 1; 2032 arg = ARG_GET(a); 2033 if (arg) { 2034 port = parse_integer(arg); 2035 2036 if (port <= 0) { 2037 cli_out("Port %s is invalid. Port numbering starts at 1.\n", arg); 2038 PTP_CLI_RESULT_RETURN(CMD_FAIL); 2039 } 2040 } 2041 2042 BCM_IF_ERROR_RETURN(ptp_show_port(unit, cur_stack_id, cur_clock_num, port)); 2043 #ifndef __KERNEL__ 2044 BCM_IF_ERROR_RETURN(ptp_show_foreign_master_dataset(unit, cur_stack_id, cur_clock_num, port)); 2045 #endif 2046 2047 PTP_CLI_RESULT_RETURN(CMD_OK); 2048 } 2049 else if (parse_cmp(arg, "Dropcounter", 0)) { 2050 2051 int port = 1; 2052 char *arg_port_drop_counter_enabled = NULL; 2053 2054 arg = ARG_GET(a); 2055 if (!arg) { 2056 PTP_CLI_RESULT_RETURN(CMD_USAGE); 2057 } 2058 2059 port = parse_integer(arg); 2060 2061 arg = ARG_GET(a); 2062 2063 if (parse_cmp("Show", arg, 0)) { 2064 bcm_ptp_clock_port_packet_drop_counters_t per_port_packet_drop_counters; 2065 memset(&per_port_packet_drop_counters, 0x0, sizeof(per_port_packet_drop_counters)); 2066 BCM_IF_ERROR_RETURN( 2067 bcm_ptp_clock_port_drop_counters_get(unit, cur_stack_id, cur_clock_num, port, 2068 &per_port_packet_drop_counters)); 2069 2070 cli_out(" Domain mismatch: %u\n", per_port_packet_drop_counters.domain_mismatch); 2071 cli_out(" Memory alloc failure: %u\n", per_port_packet_drop_counters.memory_alloc_failure); 2072 cli_out(" Pkt len too short: %u\n", per_port_packet_drop_counters.pkt_len_too_short); 2073 cli_out(" Pkt rcvd on bad port state: %u\n", per_port_packet_drop_counters.pkt_rcvd_on_bad_port_state); 2074 cli_out(" Ptp profile mismatch: %u\n", per_port_packet_drop_counters.ptp_profile_mismatch); 2075 cli_out(" Clock port mismatch: %u\n", per_port_packet_drop_counters.clock_port_mismatch); 2076 cli_out(" Ptp packet parsing failure: %u\n", per_port_packet_drop_counters.ptp_packet_parsing_failure); 2077 2078 cli_out(" Unicast delreq from unknown slave: %u\n", per_port_packet_drop_counters.unicast_delreq_from_unknown_slave); 2079 cli_out(" Announce rcvd on master only port: %u\n", per_port_packet_drop_counters.announce_rcvd_on_master_only_port); 2080 cli_out(" Announce rcvd with invalid steps removed field: %u\n", per_port_packet_drop_counters.announce_rcvd_with_invalid_steps_removed_field); 2081 cli_out(" Announce from unknown unicast master: %u\n", per_port_packet_drop_counters.announce_from_unknown_unicast_master); 2082 cli_out(" Announce rcvd on gps timesource ptp port: %u\n", per_port_packet_drop_counters.announce_rcvd_on_gps_timesource_ptp_port); 2083 2084 cli_out(" Sync rcvd invalid: %u\n", per_port_packet_drop_counters.sync_rcvd_invalid); 2085 cli_out(" Sync rcvd on ptp port without master: %u\n", per_port_packet_drop_counters.sync_rcvd_on_ptp_port_without_master); 2086 2087 } else if (parse_cmp("Config", arg, 0)) { 2088 parse_table_t pt; 2089 parse_table_init(unit, &pt); 2090 parse_table_add(&pt, "ENable", PQ_STRING, (void *)"N", &arg_port_drop_counter_enabled, NULL); 2091 2092 if (parse_arg_eq(a, &pt) < 0) { 2093 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 2094 } 2095 2096 if (parse_cmp("y", arg_port_drop_counter_enabled, 0)) { 2097 bcm_ptp_clock_port_drop_counters_enable_set(unit, cur_stack_id, cur_clock_num, port, 1); 2098 } else { 2099 bcm_ptp_clock_port_drop_counters_enable_set(unit, cur_stack_id, cur_clock_num, port, 0); 2100 } 2101 parse_arg_eq_done(&pt); 2102 } 2103 else { 2104 cli_out(" Unexpected argument '%s'\n", arg); 2105 cli_out("%s", PTP_PORT_USAGE); 2106 } 2107 PTP_CLI_RESULT_RETURN(CMD_OK); 2108 } 2109 else { 2110 cli_out(" Unexpected argument '%s'\n", arg); 2111 cli_out("%s", PTP_PORT_USAGE); 2112 2113 PTP_CLI_RESULT_RETURN(CMD_FAIL); 2114 } 2115 } 2116 2117 /* PTP Time */ 2118 #define PTP_TIME_USAGE \ 2119 "PTP Time Set or get the PTP time \n\t" \ 2120 " PTP Time Set TimeSec=<timeSec> [TimeNS=<timeNS>] \n\t" \ 2121 " PTP Time Get\n" 2122 2123 STATIC cmd_result_t 2124 cmd_ptp_time(int unit, args_t *a) 2125 { 2126 int rv; 2127 const char * arg; 2128 bcm_ptp_timestamp_t time; 2129 char uint64_decimal_string[27]; 2130 2131 arg = ARG_GET(a); 2132 if (!arg) { 2133 PTP_CLI_RESULT_RETURN(CMD_USAGE); 2134 } 2135 2136 time.nanoseconds = 0; 2137 COMPILER_64_SET(time.seconds, 0, 0); 2138 if (parse_cmp("Get", arg, 0)) { 2139 rv = bcm_ptp_clock_time_get(unit, cur_stack_id, cur_clock_num, &time); 2140 format_uint64_decimal(uint64_decimal_string, time.seconds, ','); 2141 cli_out("Time: %s.%09u\n", uint64_decimal_string, (unsigned)time.nanoseconds); 2142 if (rv) { 2143 PTP_CLI_RESULT_RETURN(CMD_FAIL); 2144 } else { 2145 PTP_CLI_RESULT_RETURN(CMD_OK); 2146 } 2147 } else if (parse_cmp("Set", arg, 0)) { 2148 int n_args = 0; 2149 parse_table_t pt; 2150 parse_table_init(unit, &pt); 2151 parse_table_add(&pt, "TimeNS", PQ_INT, 0, &time.nanoseconds, NULL); 2152 parse_table_add(&pt, "TimeSec", PQ_DFL|PQ_INT64, 0, &time.seconds, NULL); 2153 n_args = parse_arg_eq(a, &pt); 2154 if (n_args == 1 || n_args == 2) { 2155 parse_arg_eq_done(&pt); 2156 PTP_IF_ERROR_RETURN(bcm_ptp_clock_time_set(unit, cur_stack_id, cur_clock_num, &time)); 2157 PTP_CLI_RESULT_RETURN(CMD_OK); 2158 } 2159 } 2160 2161 PTP_CLI_RESULT_RETURN(CMD_USAGE); 2162 } 2163 2164 2165 2166 /* PTP Channels */ 2167 /* We divide the string because pedantic compiler doesn't allow strings longer then 509 characters */ 2168 #define PTP_CHANNELS_USAGE_1 \ 2169 "PTP CHannels Configure sources of time \n\t" \ 2170 " PTP CHannels Set Num=<num_channels> PrimaryType=<ch1_type> PrimarySource=<ch1_source>\n\t" \ 2171 " PrimaryFrequency=<ch1_freq> PrimaryFrequencyEnabled=<ch1_freq_en>\n\t" \ 2172 " PrimaryFrequencyPriority=<ch1_freqprio>\n\t" \ 2173 " PrimaryTimeEnabled=<ch1_timeenabled> PrimaryTimePriority=<ch1_timeprio>\n\t" \ 2174 " BackupTimeInputSynce=<ch1_input_synce> \n\t" 2175 #define PTP_CHANNELS_USAGE_2 \ 2176 " [BackupType=<ch2_type>] [BackupSource=<ch2_source>] \n\t" \ 2177 " [BackupFrequency=<ch2_freq>] [BackupFrequencyEnabled=<ch2_freq_en>\n\t" \ 2178 " [BackupFrequencyPriority=<ch2_freqprio>]\n\t" \ 2179 " [BackupTimeEnabled=<ch2_time_en> [BackupTimePriority=<ch2_timeprio>]\n\t" \ 2180 " [BackupSynceInputType=<0/1> [NoL1MuxSel=<0/1>\n\t" \ 2181 " PTP CHannels Get\n\t" \ 2182 " PTP CHannels STatus\n" 2183 2184 #define PTP_CHANNELS_USAGE_EXAMPLES \ 2185 " Example usage of PTP Channels:\n\t" \ 2186 " Configure to use PTP only:\n\t" \ 2187 " ptp chan set Num=1 PT=0 \n\t" \ 2188 " Configure to use PTP + 1PPS (from TS_SYNC0) , priorities 2 & 1 respectively:\n\t" \ 2189 " ptp chan set Num=2 PT=0 PFP=2 BT=6 BF=1 BFP=1 \n" 2190 2191 STATIC cmd_result_t 2192 cmd_ptp_channels(int unit, args_t *a) 2193 { 2194 cmd_result_t our_result = CMD_OK; 2195 int rv = BCM_E_NONE; 2196 const char * arg; 2197 static bcm_ptp_channel_t channels[3]; 2198 static int num_channels; 2199 int i; 2200 int show = 0; 2201 char *pri_src = 0, *bkp_src = 0; 2202 2203 arg = ARG_GET(a); 2204 if (!arg) { 2205 PTP_CLI_RESULT_RETURN(CMD_USAGE); 2206 } 2207 2208 if (parse_cmp("Set", arg, 0)) { 2209 parse_table_t pt; 2210 parse_table_init(unit, &pt); 2211 parse_table_add(&pt, "Num", PQ_INT, (void*)1, &num_channels, NULL); 2212 parse_table_add(&pt, "PrimaryType", PQ_INT, 0, &channels[0].type, NULL); 2213 parse_table_add(&pt, "PrimarySource", PQ_STRING, 0, &pri_src, NULL); 2214 parse_table_add(&pt, "PrimaryFrequency", PQ_INT, (void*)1000, &channels[0].frequency, NULL); 2215 parse_table_add(&pt, "PrimaryFrequencyPriority", PQ_INT, (void*)1, &channels[0].freq_priority, NULL); 2216 parse_table_add(&pt, "PrimaryFrequencyEnabled", PQ_INT, (void*)1, &channels[0].freq_enabled, NULL); 2217 parse_table_add(&pt, "PrimaryTimePriority", PQ_INT, (void*)1, &channels[0].time_prio, NULL); 2218 parse_table_add(&pt, "PrimaryTimeEnabled", PQ_INT, (void*)1, &channels[0].time_enabled, NULL); 2219 channels[0].synce_config_flags = 0; 2220 2221 parse_table_add(&pt, "BackupType", PQ_INT, 0, &channels[1].type, NULL); 2222 parse_table_add(&pt, "BackupSource", PQ_STRING, 0, &bkp_src, NULL); 2223 parse_table_add(&pt, "BackupFrequency", PQ_INT, (void*)1, &channels[1].frequency, NULL); 2224 parse_table_add(&pt, "BackupFrequencyPriority", PQ_INT, (void*)2, &channels[1].freq_priority, NULL); 2225 parse_table_add(&pt, "BackupFrequencyEnabled", PQ_INT, (void*)1, &channels[1].freq_enabled, NULL); 2226 parse_table_add(&pt, "BackupTimePriority", PQ_INT, (void*)2, &channels[1].time_prio, NULL); 2227 parse_table_add(&pt, "BackupTimeEnabled", PQ_INT, (void*)0, &channels[1].time_enabled, NULL); 2228 parse_table_add(&pt, "BackupTimeInputSynce", PQ_INT, (void*)2, &channels[1].synce_input_port, NULL); 2229 parse_table_add(&pt, "BackupSynceInputType", PQ_INT, (void*)0, &channels[1].synce_input_clk_type, NULL); 2230 parse_table_add(&pt, "NoL1MuxSel", PQ_INT, (void*)0, &channels[1].synce_config_flags, NULL); 2231 2232 parse_table_add(&pt, "ThirdType", PQ_INT, 0, &channels[2].type, NULL); 2233 parse_table_add(&pt, "ThirdSource", PQ_INT, 0, &channels[2].source, NULL); 2234 parse_table_add(&pt, "ThirdFrequency", PQ_INT, (void*)1, &channels[2].frequency, NULL); 2235 parse_table_add(&pt, "ThirdFrequencyPriority", PQ_INT, (void*)2, &channels[2].freq_priority, NULL); 2236 parse_table_add(&pt, "ThirdFrequencyEnabled", PQ_INT, (void*)1, &channels[2].freq_enabled, NULL); 2237 parse_table_add(&pt, "ThirdTimePriority", PQ_INT, (void*)2, &channels[2].time_prio, NULL); 2238 parse_table_add(&pt, "ThirdTimeEnabled", PQ_INT, (void*)0, &channels[2].time_enabled, NULL); 2239 channels[2].synce_config_flags = 0; 2240 2241 if (parse_arg_eq(a, &pt) < 0) { 2242 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 2243 parse_arg_eq_done(&pt); 2244 return(CMD_FAIL); 2245 } 2246 2247 if (pri_src && pri_src[0] != 0) { 2248 if (isint(pri_src)) { 2249 channels[0].source = parse_integer(pri_src); 2250 } 2251 #if (defined(BCM_ESW_SUPPORT) && !defined(__KERNEL__)) 2252 else { 2253 soc_pbmp_t pbm; 2254 if (parse_pbmp(unit, pri_src, &pbm) != 0) { 2255 cli_out("Unable to parse source pbm '%s'\n", pri_src); 2256 our_result = CMD_FAIL; 2257 } else if (soc_switch_sync_mux_from_pbm(unit, pbm, 2258 &channels[0].source) != 0) { 2259 cli_out("Unable to get mux setting for pbm '%s'\n", pri_src); 2260 our_result = CMD_FAIL; 2261 } 2262 } 2263 #endif /* ESW_SUPPORT */ 2264 } else { 2265 channels[0].source = 0; 2266 } 2267 2268 if (bkp_src && bkp_src[0] != 0) { 2269 if (isint(bkp_src)) { 2270 channels[1].source = parse_integer(bkp_src); 2271 } 2272 #if (defined(BCM_ESW_SUPPORT) && !defined(__KERNEL__)) 2273 else { 2274 soc_pbmp_t pbm; 2275 if (parse_pbmp(unit, bkp_src, &pbm) != 0) { 2276 cli_out("Unable to parse source pbm '%s'\n", bkp_src); 2277 our_result = CMD_FAIL; 2278 } else if (soc_switch_sync_mux_from_pbm(unit, pbm, 2279 &channels[1].source) != 0) { 2280 cli_out("Unable to get mux setting for pbm '%s'\n", bkp_src); 2281 our_result = CMD_FAIL; 2282 } 2283 } 2284 #endif /* ESW_SUPPORT */ 2285 } else { 2286 channels[1].source = 0; 2287 } 2288 2289 parse_arg_eq_done(&pt); 2290 2291 if (our_result != CMD_OK) { 2292 return our_result; 2293 } 2294 2295 #if defined(BCM_TRIDENT2_SUPPORT) 2296 if (SOC_IS_TRIDENT2(unit)) 2297 { 2298 /* Handle the logical to physical port mapping on Trident 2 */ 2299 if ((channels[1].synce_input_port < 0) || (channels[1].synce_input_port > 131)) { 2300 return BCM_E_PARAM; 2301 } 2302 else if ((channels[1].synce_input_port >= 0) && (channels[1].synce_input_port <= 128)) { 2303 channels[1].synce_input_port = bcm_esw_ptp_map_input_synce_clock(channels[1].synce_input_port); 2304 } 2305 } 2306 #endif 2307 rv = bcm_ptp_input_channels_set(unit, cur_stack_id, cur_clock_num, num_channels, channels); 2308 show = 1; 2309 if (rv == BCM_E_UNAVAIL) { 2310 cli_out("Channel configuration NOT supported for the servo type\n"); 2311 } 2312 2313 } else if (parse_cmp("Get", arg, 0)) { 2314 num_channels = 3; 2315 rv = bcm_ptp_input_channels_get(unit, cur_stack_id, cur_clock_num, &num_channels, channels); 2316 if (rv == BCM_E_UNAVAIL) { 2317 cli_out("Channel configuration NOT supported for the servo type\n"); 2318 } 2319 show = 1; 2320 } else if (parse_cmp("STatus", arg, 0)) { 2321 _bcm_ptp_channel_status_t channel_status[3]; 2322 int i; 2323 2324 num_channels = 3; 2325 rv = _bcm_common_ptp_input_channels_status_get(unit, cur_stack_id, cur_clock_num, &num_channels, channel_status); 2326 if (rv == BCM_E_UNAVAIL) { 2327 cli_out("Channel configuration NOT supported for the servo type\n"); 2328 } 2329 if (rv == BCM_E_NONE) { 2330 if (num_channels == 0) { 2331 cli_out("No channels returned\n"); 2332 } 2333 for (i = 0; i < num_channels; ++i) { 2334 cli_out(" channel %d: Frequency Time\n", i); 2335 cli_out("---------------------------------------\n"); 2336 cli_out(" status %8s %8s\n", 2337 (channel_status[i].freq_status == 0) ? "OK" : 2338 (channel_status[i].freq_status == 1) ? "Fault" : 2339 (channel_status[i].freq_status == 2) ? "Disabled" : "?", 2340 (channel_status[i].time_status == 0) ? "OK" : 2341 (channel_status[i].time_status == 1) ? "Fault" : 2342 (channel_status[i].time_status == 2) ? "Disabled" : "?"); 2343 cli_out(" weight %3d %3d\n", 2344 channel_status[i].freq_weight, channel_status[i].time_weight); 2345 cli_out(" QL %3d %3d\n", 2346 channel_status[i].freq_QL, channel_status[i].time_QL); 2347 cli_out("---------------------------------------\n"); 2348 cli_out(" QL %s read externally. Fault status: %08x\n", 2349 channel_status[i].ql_read_externally ? "is" : "is not", 2350 (unsigned)channel_status[i].fault_map); 2351 cli_out("\n"); 2352 } 2353 } 2354 } else if (parse_cmp("Help", arg, 0) || parse_cmp("?", arg, 0)) { 2355 cli_out(PTP_CHANNELS_USAGE_1); 2356 cli_out(PTP_CHANNELS_USAGE_2); 2357 cli_out(PTP_CHANNELS_USAGE_EXAMPLES); 2358 } else { 2359 PTP_CLI_RESULT_RETURN(CMD_USAGE); 2360 } 2361 2362 if (show && (rv == BCM_E_NONE)) { 2363 cli_out("Configured channels : %d\n",num_channels); 2364 for (i = 0; i < num_channels; i++) { 2365 cli_out("channel[%d]: type=%d, source=%d, frequency=%d, tod_index=%d, freq_prio=%d\n", i, 2366 channels[i].type, channels[i].source, channels[i].frequency, 2367 channels[i].tod_index,channels[i].freq_priority); 2368 2369 cli_out(" time_enabled=%c, freq_enabled=%c, time_prio=%d freq_assumed_QL=%d\n", 2370 channels[i].time_enabled ? 'y' : 'n', channels[i].freq_enabled ? 'y' : 'n', 2371 channels[i].time_prio,channels[i].freq_assumed_QL); 2372 2373 cli_out(" time_assumed_ql=%d, assumed_ql_enabled=%c\n", 2374 channels[i].time_assumed_QL, channels[i].assumed_QL_enabled ? 'y' : 'n'); 2375 2376 cli_out(" l1_clock_input_port=%d l1_clock_input_type=%d ", 2377 channels[i].synce_input_port, (int)channels[i].synce_input_clk_type); 2378 cli_out(" NoL1MuxSel=%08x\n", 2379 (channels[i].synce_config_flags & (1<<BCM_PTP_CHANNEL_SYNCE_CONFIG_NO_L1MUX_SELECT))); 2380 } 2381 } 2382 if (rv) { 2383 PTP_CLI_RESULT_RETURN(CMD_FAIL); 2384 } else { 2385 PTP_CLI_RESULT_RETURN(CMD_OK); 2386 } 2387 } 2388 2389 2390 /* PTP Signal */ 2391 #define PTP_SIGNAL_USAGE \ 2392 "PTP SIGnals Configure output signals \n\t" \ 2393 " PTP SIGnals Set Pin=<pin#> Frequency=<Hz> PhaseLock[=y/n] Width=<ns> Offset=<ns> OutputSynce=<output_synce> \n\t" \ 2394 " ex. \"ptp signals set p=1 freq=1 pl=y width=100000000\" for 1PPS on J603 \n\t" \ 2395 " PTP SIGnals Get\n" 2396 2397 STATIC cmd_result_t 2398 cmd_ptp_signals(int unit, args_t *a) 2399 { 2400 int rv; 2401 const char * arg; 2402 2403 static bcm_ptp_signal_output_t signal; 2404 int signal_id; 2405 int signal_count; 2406 int i; 2407 2408 arg = ARG_GET(a); 2409 if (!arg) { 2410 PTP_CLI_RESULT_RETURN(CMD_USAGE); 2411 } 2412 2413 if (parse_cmp("Get", arg, 0)) { 2414 bcm_ptp_signal_output_t sig_arr[PTP_MAX_OUTPUT_SIGNALS]; 2415 rv = bcm_ptp_signal_output_get(unit, cur_stack_id, cur_clock_num, &signal_count, sig_arr); 2416 cli_out("Configured signals : %d\n",signal_count); 2417 for (i = 0; i < PTP_MAX_OUTPUT_SIGNALS; i++) { 2418 if (sig_arr[i].frequency) 2419 { 2420 cli_out("Signal[%d]: pin=%d, frequency=%d, phaselock=%c, width=%d, offset=%d, outputsynce=%d\n", 2421 i,sig_arr[i].pin,sig_arr[i].frequency, 2422 sig_arr[i].phase_lock ? 'y' : 'n', 2423 sig_arr[i].pulse_width_ns, sig_arr[i].pulse_offset_ns, sig_arr[i].synce_output_port); 2424 } 2425 } 2426 if (rv) { 2427 PTP_CLI_RESULT_RETURN(CMD_FAIL); 2428 } else { 2429 PTP_CLI_RESULT_RETURN(CMD_OK); 2430 } 2431 } else if (parse_cmp("Set", arg, 0)) { 2432 parse_table_t pt; 2433 parse_table_init(unit, &pt); 2434 parse_table_add(&pt, "Pin", PQ_INT, (void*)1, &signal.pin, NULL); 2435 parse_table_add(&pt, "Frequency", PQ_INT, (void*)1, &signal.frequency, NULL); 2436 parse_table_add(&pt, "PhaseLock", PQ_BOOL, (void*)1, &signal.phase_lock, NULL); 2437 parse_table_add(&pt, "Width", PQ_INT, (void*)1000, &signal.pulse_width_ns, NULL); 2438 parse_table_add(&pt, "Offset", PQ_INT, 0, &signal.pulse_offset_ns, NULL); 2439 parse_table_add(&pt, "OutputSynce", PQ_INT, (void*)0, &signal.synce_output_port, NULL); 2440 if (parse_arg_eq(a, &pt) < 0) { 2441 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 2442 } 2443 parse_arg_eq_done(&pt); 2444 2445 rv = bcm_ptp_signal_output_set(unit, cur_stack_id, cur_clock_num, &signal_id, &signal); 2446 2447 if (rv) { 2448 PTP_CLI_RESULT_RETURN(CMD_FAIL); 2449 } else { 2450 PTP_CLI_RESULT_RETURN(CMD_OK); 2451 } 2452 } 2453 2454 PTP_CLI_RESULT_RETURN(CMD_USAGE); 2455 } 2456 2457 /* Configures PHY port to use 4KHz SYNC_IN0, with framesync on SYNC_IN1 */ 2458 STATIC int configure_phy_sync(int unit, bcm_port_t port, uint64 ref_phase) 2459 { 2460 int rv; 2461 bcm_port_phy_timesync_config_t config; 2462 uint64 load_control; 2463 uint64 localTime_phy; 2464 2465 sal_memset(&config, 0, sizeof(config)); 2466 2467 config.validity_mask = BCM_PORT_PHY_TIMESYNC_VALID_FLAGS | BCM_PORT_PHY_TIMESYNC_VALID_GMODE | 2468 BCM_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE | BCM_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE | 2469 BCM_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE | 2470 BCM_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE | 2471 BCM_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE | BCM_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE | 2472 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE | 2473 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA | 2474 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1 | BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2 | 2475 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3 | 2476 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_LOOP_FILTER; 2477 2478 config.flags = BCM_PORT_PHY_TIMESYNC_ENABLE | 2479 BCM_PORT_PHY_TIMESYNC_L2_ENABLE | 2480 BCM_PORT_PHY_TIMESYNC_IP4_ENABLE | 2481 BCM_PORT_PHY_TIMESYNC_IP6_ENABLE | 2482 BCM_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT; 2483 2484 config.gmode = bcmPortPhyTimesyncModeCpu; 2485 config.framesync.mode = bcmPortPhyTimesyncFramesyncSyncin1; 2486 config.syncout.mode = bcmPortPhyTimesyncSyncoutDisable; 2487 config.tx_sync_mode = bcmPortPhyTimesyncEventMessageEgressModeUpdateCorrectionField; 2488 config.rx_sync_mode = bcmPortPhyTimesyncEventMessageIngressModeUpdateCorrectionField; 2489 config.tx_delay_request_mode = bcmPortPhyTimesyncEventMessageEgressModeUpdateCorrectionField; 2490 config.rx_delay_request_mode = bcmPortPhyTimesyncEventMessageIngressModeUpdateCorrectionField; 2491 /* for 4KHz SyncIn */ 2492 config.phy_1588_dpll_ref_phase = ref_phase; 2493 config.phy_1588_dpll_ref_phase_delta = 250000; 2494 config.phy_1588_dpll_k1 = 0x2b; 2495 config.phy_1588_dpll_k2 = 0x26; 2496 config.phy_1588_dpll_k3 = 0; 2497 2498 /* Initial value for the loop filter: 0x8000 0000 0000 0000 */ 2499 COMPILER_64_SET(config.phy_1588_dpll_loop_filter, 0x80000000, 0); 2500 2501 rv = bcm_port_phy_timesync_config_set(unit, port, &config); 2502 2503 if (rv != BCM_E_NONE) { 2504 cli_out("bcm_port_phy_timesync_config_set failed with error u=%d p=%d %s\n", unit, port, bcm_errmsg(rv)); 2505 return rv; 2506 } 2507 2508 /* use ref_phase as local time for now */ 2509 localTime_phy = _bcm_ptp_llu_div(ref_phase, 16); 2510 rv = bcm_port_control_phy_timesync_set(unit, port, bcmPortControlPhyTimesyncLocalTime, 2511 /*ref_phase*/localTime_phy); 2512 2513 if (rv != BCM_E_NONE) { 2514 cli_out("bcm_port_control_phy_timesync_set failed with error u=%d p=%d %s\n", unit, port, bcm_errmsg(rv)); 2515 return rv; 2516 } 2517 2518 COMPILER_64_SET(load_control, 0, 2519 BCM_PORT_PHY_TIMESYNC_TN_LOAD | 2520 BCM_PORT_PHY_TIMESYNC_TIMECODE_LOAD | 2521 BCM_PORT_PHY_TIMESYNC_SYNCOUT_LOAD | 2522 BCM_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD | 2523 BCM_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD | 2524 BCM_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD | 2525 BCM_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD | 2526 BCM_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD | 2527 BCM_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD | 2528 BCM_PORT_PHY_TIMESYNC_DPLL_K3_LOAD | 2529 BCM_PORT_PHY_TIMESYNC_DPLL_K2_LOAD | 2530 BCM_PORT_PHY_TIMESYNC_DPLL_K1_LOAD ); 2531 2532 rv = bcm_port_control_phy_timesync_set(unit, port, bcmPortControlPhyTimesyncLoadControl, load_control); 2533 2534 if (rv != BCM_E_NONE) { 2535 cli_out("bcm_port_control_phy_timesync_set failed with error u=%d p=%d %s\n", unit, port, bcm_errmsg(rv)); 2536 return rv; 2537 } 2538 2539 return BCM_E_NONE; 2540 } 2541 2542 STATIC int bcm_ptp_external_phy_sync_user_func( 2543 int unit, int stack_id, int clock_num, 2544 bcm_pbmp_t pbm, /* external phy port bitmap e.g ge0-ge3*/ 2545 uint64 ref_phase /* reference phase to configure */ 2546 ) 2547 { 2548 2549 int rv = BCM_E_NONE; 2550 soc_port_t p, dport; 2551 bcm_ptp_port_identity_t portid; 2552 2553 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, cur_stack_id, cur_clock_num, 2554 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 2555 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 2556 return rv; 2557 } 2558 2559 if (BCM_FAILURE(rv = bcm_ptp_clock_port_identity_get(unit, cur_stack_id, 2560 cur_clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 2561 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 2562 return rv; 2563 } 2564 2565 /* coverity[overrun-local] */ 2566 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 2567 if ((rv = configure_phy_sync(unit, p, ref_phase)) != BCM_E_NONE) { 2568 return rv; 2569 } 2570 } 2571 2572 return rv; 2573 } 2574 2575 #define PTP_SYNCPHY_USAGE \ 2576 "PTP SyncPhy Synchronize 1588-aware PHYs \n\t" \ 2577 " PTP SyncPhy PBM=<port bitmap> [FrameSyncPin=<pin#>] [SyncPin=<pin#>] [UsePHYSYNCcb=<1/0>]\n\t" \ 2578 " defaults are FrameSyncPin=3, SyncPin=-1 (-1 corresponds to BroadSync Heartbeat),UsePHYSYNCcb=0 \n" 2579 2580 STATIC cmd_result_t 2581 cmd_ptp_syncphy(int unit, args_t *a) 2582 { 2583 int rv; 2584 2585 int freq_pin = -1; /* -1 implies BroadSync Heartbeat */ 2586 int UsePHYSYNCcb= 0; /* For testing 1-> use new PHY SYNC API and callback */ 2587 int framesync_pin = 3; 2588 char *pbm_str = 0; 2589 pbmp_t pbm; 2590 soc_port_t p, dport; 2591 bcm_ptp_sync_phy_input_t sync_input; 2592 bcm_ptp_bs_time_info_t bshblocalTime ; 2593 uint64 physyncTime_nsec; 2594 uint8 physync_reqd = 0; 2595 int tmp = 0, tmp1= 0; 2596 2597 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 2598 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 2599 bcm_ptp_port_identity_t portid; 2600 2601 bcm_ptp_external_phy_config_t extphy_config; 2602 2603 parse_table_t pt; 2604 parse_table_init(unit, &pt); 2605 parse_table_add(&pt, "SyncPin", PQ_INT, (void*)-1, &freq_pin, NULL); 2606 parse_table_add(&pt, "FrameSyncPin", PQ_INT, (void*)3, &framesync_pin, NULL); 2607 parse_table_add(&pt, "PBM", PQ_STRING, (void*)"", &pbm_str, NULL); 2608 parse_table_add(&pt, "UsePHYSYNCcb",PQ_INT,(void*)0,&UsePHYSYNCcb,NULL); /* added for testing PHY SYNC callback */ 2609 if (parse_arg_eq(a, &pt) < 0) { 2610 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 2611 } 2612 2613 rv = parse_bcm_pbmp(unit, pbm_str, &pbm); 2614 2615 parse_arg_eq_done(&pt); /* free argument string */ 2616 2617 if (rv < 0) { 2618 cli_out("Invalid port bitmap\n"); 2619 cli_out("%s", PTP_SYNCPHY_USAGE); 2620 return CMD_FAIL; 2621 } 2622 2623 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, cur_stack_id, cur_clock_num, 2624 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 2625 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 2626 return rv; 2627 } 2628 2629 if (BCM_FAILURE(rv = bcm_ptp_clock_port_identity_get(unit, cur_stack_id, 2630 cur_clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 2631 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 2632 return rv; 2633 } 2634 2635 if (UsePHYSYNCcb) { 2636 2637 extphy_config.framesync_pin = framesync_pin; 2638 extphy_config.freq_pin = freq_pin; 2639 /* Adding 1.5 sec */ 2640 extphy_config.cpu_latency_nsec = 0; 2641 COMPILER_64_ADD_32(extphy_config.cpu_latency_nsec, 1000000000); 2642 COMPILER_64_ADD_32(extphy_config.cpu_latency_nsec, 500000000); 2643 extphy_config.pbm = pbm; 2644 extphy_config.ext_physync_func = bcm_ptp_external_phy_sync_user_func; 2645 2646 rv = bcm_ptp_external_phy_synchronize(unit, cur_stack_id, cur_clock_num, extphy_config); 2647 return rv; 2648 } 2649 2650 for (tmp = 0; tmp <5; tmp++) { 2651 2652 cli_out("PHY synchronization iteration..: %d\n", tmp); 2653 2654 /* NEW API implemented to query the BSHB0/1 time when TDPLL is running */ 2655 2656 rv = bcm_ptp_bs_time_info_get(unit,cur_stack_id,cur_clock_num,&bshblocalTime); 2657 2658 if (rv) { 2659 cli_out("Issue with bcm_ptp_sync_phyTime API response from TDPLL fw.....Error code:%d\n",rv); 2660 PTP_CLI_RESULT_RETURN(CMD_FAIL); 2661 } 2662 2663 2664 /* Perform initial framesync, so that pin is pulled low */ 2665 sal_memset(&sync_input, 0, sizeof(bcm_ptp_sync_phy_input_t)); 2666 sync_input.framesync_pin = framesync_pin; 2667 sync_input.freq_pin= freq_pin; 2668 2669 /* 2670 * PHY synchronization. 2671 * Calculate reference phase to program PHYs. 2672 * Reference phase based on local time (i.e. when stack is queried for 2673 * PHY synchronization state) plus sufficient delta to guarantee stack 2674 * can receive and process PHY framesync at BSHB which corresponds to 2675 * programmed phase. 2676 */ 2677 if(freq_pin == -2) { /*BSHB1 timestamp*/ 2678 physyncTime_nsec = bshblocalTime.bshb1_time; 2679 } else { 2680 physyncTime_nsec = bshblocalTime.bshb0_time; 2681 } 2682 /* Adding 1.5 sec */ 2683 COMPILER_64_ADD_32(physyncTime_nsec, 1000000000); 2684 COMPILER_64_ADD_32(physyncTime_nsec, 500000000); 2685 2686 /* For 54240 PHY , REF_PHASE = {REF_PHASE_2(15:0),REF_PHASE_1(15:0)_,REF_PHASE_0(15:0)} 2687 * Note : REF_PHASE is 48bits unlike LOCAL_TIME which is 44bits 2688 */ 2689 /* COMPILER_64_ZERO(sync_input.reference_time);*/ 2690 sync_input.reference_time = physyncTime_nsec; 2691 2692 /* Perform initial framesync, so that pin is pulled low */ 2693 rv = bcm_ptp_sync_phy(unit, cur_stack_id, cur_clock_num, sync_input); 2694 if (rv) { 2695 PTP_CLI_RESULT_RETURN(CMD_FAIL); 2696 } 2697 2698 /* delay 1ms for the framesync to happen */ 2699 sal_usleep(1000); 2700 2701 /* coverity[overrun-local] */ 2702 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 2703 if (configure_phy_sync(unit, p, physyncTime_nsec) != BCM_E_NONE) { 2704 PTP_CLI_RESULT_RETURN(CMD_FAIL); 2705 } 2706 } 2707 2708 /* Perform the actual framesync so that programmed PHY values are loaded */ 2709 rv = bcm_ptp_sync_phy(unit, cur_stack_id, cur_clock_num, sync_input); 2710 2711 #ifdef COMPILER_HAS_LONGLONG 2712 /*Debug logs added here to avoid any latency */ 2713 if(-2 == freq_pin) { /*BSHB1 timestamp*/ 2714 cli_out("****BS1 selected for SYNC_IN0 ,BS1 HB Time:%lld\n",(long long)bshblocalTime.bshb1_time); 2715 cli_out("REF_PHASE Configured with value : %lld\n",(long long)physyncTime_nsec); 2716 } else { /*default BSHB0 timestamp */ 2717 cli_out("****BS0 selected for SYNC_IN0 ,BS0 HB Time:%lld\n",(long long)bshblocalTime.bshb0_time); 2718 cli_out("REF_PHASE Configured with value : %lld\n",(long long)physyncTime_nsec); 2719 } 2720 #endif 2721 2722 for (tmp1=0; tmp1<10; tmp1++) { 2723 /* Query stack to determine whether PHY synchronization is required. */ 2724 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, cur_stack_id, 2725 cur_clock_num, &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_PHYSYNC_STATE, 2726 0, 0, resp, &resp_len))) { 2727 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 2728 return rv; 2729 } 2730 2731 /* 2732 * Parse response. 2733 * Octet 0...5 : Custom management message key/identifier. 2734 * BCM<null><null><null>. 2735 * Octet 6 : PHY synchronization required Boolean. 2736 * Octet 7 : Reserved. 2737 * Octet 8...15 : Stack local time (sec). 2738 * Octet 16...19: stack local time (nsec). 2739 */ 2740 physync_reqd = resp[6]; 2741 2742 /* PHY synchronization. */ 2743 if (physync_reqd == 3) { 2744 /* PHY synchronization is not required. */ 2745 cli_out("PHY synchronization complete or not required %d\n", physync_reqd); 2746 PTP_CLI_RESULT_RETURN(CMD_OK); 2747 } 2748 else { 2749 cli_out("PHY synchronization state %d\n", physync_reqd); 2750 sal_sleep(1); 2751 continue; 2752 } 2753 } 2754 } 2755 2756 cli_out("PHY synchronization failed ......\n"); 2757 if (rv) { 2758 PTP_CLI_RESULT_RETURN(CMD_FAIL); 2759 } else { 2760 PTP_CLI_RESULT_RETURN(CMD_OK); 2761 } 2762 2763 } 2764 2765 2766 #ifndef __KERNEL__ 2767 2768 #define PTP_TODOUT_USAGE_1\ 2769 "PTP ToDOut [EtherNet] <setting> [OffsetNS=<offsetNS>] [OffsetSec=<offsetSec>]\n" \ 2770 " [Delay=<delayNS>] [CustomFormat=<format_string>] [PPSJitter=<nsec>]\n" \ 2771 " [DestMac=<dmac>] [SrcMac=<smac>] [VLAN=<vid>] [EtherType=<etype>] [BaudRate=<baudrate>]\n" \ 2772 " where <setting> = | Off | NMEAzda | ISO8601 | NTP | UBlox |\n" \ 2773 " | ChinaMobile | ChinaTelecom | BCM | BCMTS | CUSTom |\n" \ 2774 " supported baudrates are 300|600|1200|1800|2400|4800|9600|19200|38400|57600|115200|230400 \n"\ 2775 " Examples:\n" 2776 2777 #define PTP_TODOUT_USAGE_2\ 2778 " PTP ToDOut ISO8601 Delay=50000000 OffsetSec=1 BaudRate=9600\n" \ 2779 " Configure UART output with ISO format, delayed from 1PPS edge by 50ms,\n" \ 2780 " and outputting the time associated with the following 1PPS edge\n" \ 2781 " PTP ToDOut EtherNet BCM DestMac=00:00:01:00:00:01 SrcMac=00:00:02:00:00:02 VLAN=1 EtherType=0x5006\n" \ 2782 " Configure Ethernet output with Broadcom binary format, with specified L2 information\n" \ 2783 " PTP ToDOut EtherNet off\n" \ 2784 " Disable Ethernet TOD output\n" 2785 2786 STATIC cmd_result_t 2787 cmd_ptp_tod_out(int unit, args_t *a) 2788 { 2789 parse_table_t pt; 2790 const char *format = ARG_GET(a); 2791 char *custom_format_str = 0; 2792 bcm_ptp_tod_output_t tod = {0}; 2793 bcm_ptp_tod_source_t source = bcmPTPTODSourceSerial; 2794 int output_id = 1; 2795 2796 int vlan, ethertype; 2797 int uartNum; 2798 2799 const char * nmea_str = "$GPZDA,%H%M%S.00,%d,%m,%Y,00,00*\\*\\r\\n"; 2800 const char * iso_str = "%Y-%m-%dT%H:%M:%SZ\\r\\n"; 2801 const char * ntp_str = " %y %j %H:%M:%S.000 S\\r\\n"; 2802 const char * format_str = 0; 2803 2804 int arg_pps_jitter; 2805 2806 if (format && parse_cmp("EtherNet", format, 0)) { 2807 source = bcmPTPTODSourceEthernet; 2808 output_id = 2; 2809 format = ARG_GET(a); 2810 } 2811 2812 if (!format) { 2813 PTP_CLI_RESULT_RETURN(CMD_USAGE); 2814 } 2815 2816 tod.source = source; 2817 tod.frequency = 1; 2818 2819 parse_table_init(unit, &pt); 2820 parse_table_add(&pt, "OffsetNS", PQ_INT, (void*)0, &tod.tod_offset_ns, NULL); 2821 parse_table_add(&pt, "OffsetSec", PQ_INT, (void*)0, &tod.tod_offset_src, NULL); 2822 parse_table_add(&pt, "Delay", PQ_INT, (void*)0, &tod.tod_delay_ns, NULL); 2823 parse_table_add(&pt, "CustomFormat", PQ_STRING, (void*)"", &custom_format_str, NULL); 2824 parse_table_add(&pt, "PPSJitter", PQ_INT, (void*)0, &arg_pps_jitter, NULL); 2825 parse_table_add(&pt, "DestMac", PQ_MAC | PQ_DFL, (void*)0, &tod.peer_address.raw_l2_header[0], NULL); 2826 parse_table_add(&pt, "SrcMac", PQ_MAC | PQ_DFL, (void*)0, &tod.peer_address.raw_l2_header[6], NULL); 2827 parse_table_add(&pt, "VLAN", PQ_INT, (void*)1, &vlan, NULL); 2828 parse_table_add(&pt, "EtherType", PQ_INT, (void*)BCM_TOD_ETHERTYPE, ðertype, NULL); 2829 parse_table_add(&pt, "BaudRate", PQ_INT, (void*)0, &tod.tod_baud_rate, NULL); 2830 parse_table_add(&pt, "UartNum", PQ_INT, (void*)0, &uartNum, NULL); 2831 2832 if (parse_arg_eq(a, &pt) < 0) { 2833 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 2834 } 2835 2836 cli_out("ptp_tod_out UartNum:%d\n", uartNum); 2837 if ((uartNum == 0) && (bcmPTPTODSourceEthernet != source)) 2838 tod.source = bcmPTPTODSourceSerial; 2839 else if ((uartNum == 1) && (bcmPTPTODSourceEthernet != source)) 2840 tod.source = bcmPTPTODSourceSerial1; 2841 else if ((uartNum == 2) && (bcmPTPTODSourceEthernet != source)) 2842 tod.source = bcmPTPTODSourceSerial2; 2843 else if ((uartNum == 3) && (bcmPTPTODSourceEthernet != source)) 2844 tod.source = bcmPTPTODSourceSerial3; 2845 2846 cli_out("ptp_tod_out tod.source=%d\n", tod.source); 2847 2848 if (parse_cmp("NMEAzda", format, 0)) { 2849 format_str = nmea_str; 2850 } else if (parse_cmp("ISO8601", format, 0)) { 2851 format_str = iso_str; 2852 } else if (parse_cmp("NTP", format, 0)) { 2853 format_str = ntp_str; 2854 } else if (parse_cmp("CUSTom", format, 0)) { 2855 format_str = custom_format_str; 2856 } 2857 2858 if (source == bcmPTPTODSourceEthernet) { 2859 /* insert a vlan tag after the dest/src MACs */ 2860 _bcm_ptp_uint16_write(tod.peer_address.raw_l2_header + 12, 0x8100); 2861 _bcm_ptp_uint16_write(tod.peer_address.raw_l2_header + 14, vlan); 2862 _bcm_ptp_uint16_write(tod.peer_address.raw_l2_header + 16, ethertype); 2863 tod.peer_address.raw_l2_header_length = 18; 2864 } 2865 2866 if (format_str) { 2867 /* we've got the format string, so use it */ 2868 tod.format = bcmPTPTODFormatString; 2869 sal_strncpy((char *)tod.format_str, format_str, BCM_PTP_MAX_TOD_FORMAT_STRING - 1); 2870 tod.format_str_len = sal_strlen(format_str); 2871 if (tod.format_str_len > BCM_PTP_MAX_TOD_FORMAT_STRING) { 2872 tod.format_str_len = BCM_PTP_MAX_TOD_FORMAT_STRING; 2873 } 2874 } else if (parse_cmp("UBlox", format, 0)) { 2875 tod.format = bcmPTPTODFormatUBlox; 2876 tod.format_str[0] = 0x00; /* UBlox flags. */ 2877 tod.format_str_len = 1; 2878 } else if (parse_cmp("ChinaMobile", format, 0)) { 2879 tod.format = bcmPTPTODFormatChinaTcom; 2880 sal_sprintf((char *)tod.format_str, "CM %05u", (uint16)arg_pps_jitter); 2881 tod.format_str_len = 8; 2882 } else if (parse_cmp("ChinaTelecom", format, 0)) { 2883 tod.format = bcmPTPTODFormatChinaTcom; 2884 sal_sprintf((char *)tod.format_str, "CT %05u", (uint16)arg_pps_jitter); 2885 tod.format_str_len = 8; 2886 } else if (parse_cmp("BCMTS", format, 0)) { 2887 tod.format = bcmPTPTODFormatBCMTS; 2888 } else if (parse_cmp("BCM", format, 0)) { 2889 tod.format = bcmPTPTODFormatBCM; 2890 } else if (parse_cmp("Off", format, 0)) { 2891 PTP_IF_ERROR_RETURN(bcm_ptp_tod_output_remove(unit, cur_stack_id, cur_clock_num, output_id)); 2892 PTP_CLI_RESULT_RETURN(CMD_OK); 2893 } else { 2894 parse_arg_eq_done(&pt); /* will free 'custom_format_str' */ 2895 PTP_CLI_RESULT_RETURN(CMD_USAGE); 2896 } 2897 2898 parse_arg_eq_done(&pt); /* will free 'custom_format_str' */ 2899 2900 PTP_IF_ERROR_RETURN(bcm_ptp_tod_output_set(unit, cur_stack_id, cur_clock_num, &output_id, &tod)); 2901 2902 PTP_CLI_RESULT_RETURN(CMD_OK); 2903 } 2904 2905 /* PTP ToDIn */ 2906 #define PTP_TODIN_USAGE_1 \ 2907 "PTP ToDIn [EtherNet] <setting> [OffsetNS=<offsetNS>] [OffsetSec=<offsetSec>]\n" \ 2908 " [CustomFormat=<format_string>] [CustomMask=<mask_string>]\n" \ 2909 " [DestMac=<dmac>] [SrcMac=<smac>] [VLAN=<vid>] [EtherType=<etype>] \n" \ 2910 " where <setting> = | Off | NMEAzda | ISO8601 | NTP | UBlox |\n" \ 2911 " | ChinaMobile | ChinaTelecom | BCM | BCMTS | CUSTom |\n" \ 2912 " Examples:\n" 2913 2914 #define PTP_TODIN_USAGE_2\ 2915 " PTP ToDIn ISO8601 OffsetSec=1 OffsetNS=0 BaudRate=9600\n" \ 2916 " Configure ToD input via UART with ISO format,\n" \ 2917 " PTP ToDIn EtherNet BCM DestMac=00:00:01:00:00:01 SrcMac=00:00:02:00:00:02 VLAN=1 EtherType=0x5006\n" \ 2918 " Configure ToD input via Ethernet with Broadcom binary format, with specified L2 information\n" \ 2919 " PTP ToDIn off\n" \ 2920 " Disable ToD input\n" 2921 2922 STATIC cmd_result_t 2923 cmd_ptp_tod_in(int unit, args_t *a) 2924 { 2925 parse_table_t pt; 2926 const char *format = ARG_GET(a); 2927 char *custom_format_str = 0; 2928 char *custom_mask_str = 0; 2929 bcm_ptp_tod_input_t tod = {0}; /* initialize to all zero */ 2930 2931 /* NMEA ZDA "$GPZDA,HHMMSS.00,DD,MM,YYYY,zz,zz*CC"*/ 2932 const char * nmea_mask_str = " x xxxx x x xxxxxxxxx"; 2933 const char * nmea_fmt_str = "$GPZDA %2H%2M%2S %d %m %Y"; 2934 2935 /* ISO "YYYY-MM-DDTHH:MM:SS.000Z" "*/ 2936 const char * iso_mask_str = " xxxxx"; 2937 const char * iso_fmt_str = "%Y-%m-%dT%H:%M:%S"; 2938 2939 /* NTP " YY JJ HH:MM:SS.000 S" */ 2940 const char * ntp_mask_str = "xx x x xxxx"; 2941 const char * ntp_fmt_str = " %y %j %H %M %S "; 2942 2943 const char * format_str = 0; 2944 const char * mask_str = 0; 2945 2946 int vlan, ethertype; 2947 int uartNum; 2948 2949 char * blank_str = ""; 2950 int i, num_sources = 1; 2951 2952 /* By default the source is set as Serial. */ 2953 tod.source = bcmPTPTODSourceSerial; 2954 2955 if (format && parse_cmp("EtherNet", format, 0)) { 2956 tod.source = bcmPTPTODSourceEthernet; 2957 format = ARG_GET(a); 2958 } 2959 2960 if (format && parse_cmp("Off", format, 0)) { 2961 tod.source = bcmPTPTODSourceNone; 2962 } 2963 2964 if (!format) { 2965 PTP_CLI_RESULT_RETURN(CMD_USAGE); 2966 } 2967 2968 parse_table_init(unit, &pt); 2969 parse_table_add(&pt, "OffsetSec", PQ_INT, (void*)0, &tod.tod_offset_sec, NULL); 2970 parse_table_add(&pt, "OffsetNS", PQ_INT, (void*)0, &tod.tod_offset_ns, NULL); 2971 parse_table_add(&pt, "CustomFormat", PQ_STRING, blank_str, &custom_format_str, NULL); 2972 parse_table_add(&pt, "CustomMask", PQ_STRING, blank_str, &custom_mask_str, NULL); 2973 parse_table_add(&pt, "DestMac", PQ_MAC | PQ_DFL, (void*)0, &tod.peer_address.raw_l2_header[0], NULL); 2974 parse_table_add(&pt, "SrcMac", PQ_MAC | PQ_DFL, (void*)0, &tod.peer_address.raw_l2_header[6], NULL); 2975 parse_table_add(&pt, "VLAN", PQ_INT, (void*)0, &vlan, NULL); 2976 parse_table_add(&pt, "EtherType", PQ_INT, (void*)BCM_TOD_ETHERTYPE, ðertype, NULL); 2977 parse_table_add(&pt, "BaudRate", PQ_INT, (void*)0, &tod.tod_baud_rate, NULL); 2978 parse_table_add(&pt, "UartNum", PQ_INT, (void*)1, &uartNum, NULL); 2979 2980 if (parse_arg_eq(a, &pt) < 0) { 2981 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 2982 } 2983 2984 cli_out("ptp_tod_in UartNum:%d\n", uartNum); 2985 2986 if (tod.source == bcmPTPTODSourceSerial) { 2987 if (uartNum == 0) 2988 tod.source = bcmPTPTODSourceSerial; 2989 else if (uartNum == 1) 2990 tod.source = bcmPTPTODSourceSerial1; 2991 else if (uartNum == 2) 2992 tod.source = bcmPTPTODSourceSerial2; 2993 else if (uartNum == 3) 2994 tod.source = bcmPTPTODSourceSerial3; 2995 } 2996 2997 if (parse_cmp("NMEAzda", format, 0)) { 2998 format_str = nmea_fmt_str; 2999 mask_str = nmea_mask_str; 3000 } else if (parse_cmp("ISO8601", format, 0)) { 3001 format_str = iso_fmt_str; 3002 mask_str = iso_mask_str; 3003 } else if (parse_cmp("NTP", format, 0)) { 3004 format_str = ntp_fmt_str; 3005 mask_str = ntp_mask_str; 3006 } else if (parse_cmp("CUSTom", format, 0)) { 3007 format_str = custom_format_str; 3008 mask_str = custom_mask_str; 3009 } 3010 3011 /* Look for a non-zero byte in the SMAC/DMAC, to indicate that we were given ethernet info */ 3012 for (i = 0; i < 2 * sizeof(bcm_mac_t); ++i) { 3013 if (tod.peer_address.raw_l2_header[i] != 0) { 3014 tod.peer_address.raw_l2_header_length = 18; 3015 3016 if (vlan) { 3017 /* insert a vlan tag after the dest/src MACs */ 3018 _bcm_ptp_uint16_write(tod.peer_address.raw_l2_header + 12, 0x8100); 3019 _bcm_ptp_uint16_write(tod.peer_address.raw_l2_header + 14, vlan); 3020 } 3021 _bcm_ptp_uint16_write(tod.peer_address.raw_l2_header + 16, ethertype); 3022 break; 3023 } 3024 } 3025 3026 if ( (tod.source == bcmPTPTODSourceEthernet) && 3027 (tod.peer_address.raw_l2_header_length != 18)) { 3028 cli_out(" Invalid Ethernet header configuration \n"); 3029 PTP_CLI_RESULT_RETURN(CMD_USAGE); 3030 } 3031 3032 if (format_str) { 3033 /* we've got the format string, so use it */ 3034 tod.format = bcmPTPTODFormatString; 3035 sal_strncpy((char *)tod.format_str, format_str, BCM_PTP_MAX_TOD_FORMAT_STRING - 1); 3036 sal_strncpy((char *)tod.mask_str, mask_str, BCM_PTP_MAX_TOD_FORMAT_STRING - 1); 3037 } else if (parse_cmp("UBlox", format, 0)) { 3038 tod.format = bcmPTPTODFormatUBlox; 3039 } else if (parse_cmp("ChinaMobile", format, 0)) { 3040 tod.format = bcmPTPTODFormatChinaTcom; /* China Mobile/Telecom use same enumerator. */ 3041 } else if (parse_cmp("ChinaTelecom", format, 0)) { 3042 tod.format = bcmPTPTODFormatChinaTcom; /* China Mobile/Telecom use same enumerator. */ 3043 } else if (parse_cmp("BCMTS", format, 0)) { 3044 tod.format = bcmPTPTODFormatBCMTS; 3045 } else if (parse_cmp("BCM", format, 0)) { 3046 tod.format = bcmPTPTODFormatBCM; 3047 } else if (parse_cmp("Off", format, 0)) { 3048 tod.source = bcmPTPTODSourceNone; 3049 } else { 3050 parse_arg_eq_done(&pt); /* will free 'custom_format_str' and 'custom_mask_str' */ 3051 PTP_CLI_RESULT_RETURN(CMD_USAGE); 3052 } 3053 3054 parse_arg_eq_done(&pt); /* will free 'custom_format_str' and 'custom_mask_str' */ 3055 3056 cli_out("ptp_tod_in tod.source=%d\n", tod.source); 3057 3058 PTP_IF_ERROR_RETURN(bcm_ptp_tod_input_sources_set(unit, cur_stack_id, cur_clock_num, num_sources, &tod)); 3059 3060 PTP_CLI_RESULT_RETURN(CMD_OK); 3061 } 3062 3063 /* PTP Debug */ 3064 #define PTP_DEBUG_USAGE \ 3065 "PTP DeBug [[+/-]<option> ...] \n\t" \ 3066 " Set or clear debug options, +option adds to list of output, \n\t" \ 3067 " -option removes from list, no +/- toggles current state. \n\t" \ 3068 " If no options given, a current list is printed out.\n\t" \ 3069 " Note: Debug output is disabled until the first use of this command\n" 3070 3071 3072 /* Utility function: */ 3073 STATIC cmd_result_t 3074 diag_set_debug(int unit, bcm_ptp_stack_id_t stack_id, int clock_num, uint32 debug_mask, uint64 log_mask) 3075 { 3076 3077 PTP_IF_ERROR_RETURN(_bcm_ptp_system_log_configure(unit, stack_id, clock_num, 3078 diag_debug_mask[unit][stack_id], 3079 diag_log_mask[unit][stack_id], 3080 log_src_mac_addr, log_dst_mac_addr, 3081 log_tpid, log_vid, log_ttl, log_src_ip_addr, log_dst_ip_addr, log_port)); 3082 3083 PTP_CLI_RESULT_RETURN(CMD_OK); 3084 } 3085 3086 3087 STATIC cmd_result_t 3088 cmd_ptp_debug(int unit, args_t *a) 3089 { 3090 const char * arg; 3091 int stack_id = 0; 3092 int clock_num = 0; 3093 3094 int vlan_id, port_num, tpid, ttl, show_param; 3095 bcm_ip_t dst_ip = 0, src_ip = 0; 3096 bcm_mac_t blank_mac = {0}; 3097 bcm_mac_t dst_mac = {0}; 3098 bcm_mac_t src_mac = {0}; 3099 3100 parse_pm_t opt_list[] = { 3101 { "@SYs_All", 0x0000000f }, 3102 { "SYs_Info", 0x00000001 }, 3103 { "SYs_Warning", 0x00000002 }, 3104 { "SYs_Error", 0x00000004 }, 3105 { "SYs_Critical", 0x00000008 }, 3106 { "@STack_All", 0x000000f0 }, 3107 { "STack_Info", 0x00000010 }, 3108 { "STack_Warning", 0x00000020 }, 3109 { "STack_Error", 0x00000040 }, 3110 { "STack_Critical", 0x00000080 }, 3111 { "Servo_Timestamps", 0x00000100 }, 3112 { "Servo_Diagnostics", 0x00000200 }, 3113 { "Servo_Output", 0x00000400 }, 3114 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 3115 { "Extservo_SyncErr", 0x00010000 }, 3116 { "Extservo_SyncWarn", 0x00020000 }, 3117 { "Extservo_SyncAnal", 0x00040000 }, 3118 { "Extservo_Err", 0x00080000 }, 3119 { "Extservo_Warn", 0x00100000 }, 3120 { "Extservo_Debug", 0x00200000 }, 3121 { "Extservo_Trace", 0x00400000 }, 3122 { "Extservo_TimeStamps", 0x00800000 }, 3123 { "Extservo_NonStackall", 0x00FF0000 }, 3124 #endif 3125 { "Servo_Channels", 0x01000000 }, 3126 { 0, 0} 3127 }; 3128 3129 parse_table_t pt; 3130 parse_table_init(unit, &pt); 3131 parse_table_add(&pt, "DMAC", PQ_MAC, (void*)0, dst_mac, NULL); 3132 parse_table_add(&pt, "SMAC", PQ_MAC, (void*)0, src_mac, NULL); 3133 parse_table_add(&pt, "TPid", PQ_INT, (void*)0, &tpid, NULL); 3134 parse_table_add(&pt, "Vlan", PQ_INT, (void*)0, &vlan_id, NULL); 3135 parse_table_add(&pt, "DstIP", PQ_IP, (void*)0, &dst_ip, NULL); 3136 parse_table_add(&pt, "SrcIP", PQ_IP, (void*)0, &src_ip, NULL); 3137 parse_table_add(&pt, "TTL", PQ_INT, (void*)0, &ttl, NULL); 3138 parse_table_add(&pt, "PORTnum", PQ_INT, (void*)0, &port_num, NULL); 3139 parse_table_add(&pt, "SHOWparam", PQ_BOOL, (void*)0, &show_param, NULL); 3140 3141 sal_dpc_cancel(INT_TO_PTR(&output_current_debug)); 3142 output_current_debug(INT_TO_PTR(&output_current_debug), INT_TO_PTR(1000), INT_TO_PTR(0), 0, 0); 3143 3144 /* In future, when multiple stacks/clocks are in use, ARG_CUR() */ 3145 /* can be used to peek for a "Stack=" or "Clock=" argument */ 3146 3147 if (ARG_CNT(a) == 0) { 3148 cli_out("Debugging is enabled for:\n\n"); 3149 parse_mask_format(55, opt_list, diag_debug_mask[unit][stack_id]); 3150 cli_out("Debugging is disabled for:\n\n"); 3151 parse_mask_format(55, opt_list, ~diag_debug_mask[unit][stack_id]); 3152 cli_out("\n"); 3153 cli_out("Other permissible options: SYs_All, STack_All\n"); 3154 PTP_CLI_RESULT_RETURN(CMD_OK); 3155 } 3156 3157 arg = ARG_CUR(a); 3158 while (arg) { 3159 /* extract debug mask */ 3160 if (arg[0] == '0' && arg[1] == 'x') { 3161 diag_debug_mask[unit][stack_id] = parse_integer((char*)arg); 3162 } else if (parse_mask(arg, opt_list, &diag_debug_mask[unit][stack_id])) { 3163 /* Not a mask arg. Break from 'while' so other args are parsed */ 3164 break; 3165 } 3166 ARG_NEXT(a); 3167 arg = ARG_CUR(a); 3168 } 3169 3170 if (ARG_CNT(a)) { 3171 /* extract parameters to configure log header */ 3172 if (parse_arg_eq(a, &pt) < 0) { 3173 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 3174 } else { 3175 3176 if (sal_memcmp(dst_mac, blank_mac, 6)) { 3177 sal_memcpy(log_dst_mac_addr, dst_mac, 6); 3178 } 3179 if (sal_memcmp(src_mac, blank_mac, 6)) { 3180 sal_memcpy(log_src_mac_addr, src_mac, 6); 3181 } 3182 if (dst_ip) { 3183 log_dst_ip_addr = dst_ip; 3184 } 3185 if (src_ip) { 3186 log_src_ip_addr = src_ip; 3187 } 3188 if (port_num) { 3189 log_port = port_num; 3190 } 3191 if (tpid) { 3192 log_tpid = tpid; 3193 } 3194 if (vlan_id) { 3195 log_vid = vlan_id; 3196 } 3197 if (ttl) { 3198 log_ttl = ttl; 3199 } 3200 3201 if (show_param) { 3202 cli_out("\n ----- Header parameters for UDP log ----- "); 3203 cli_out("\n Destination mac : 0x%02x:%02x:%02x:%02x:%02x:%02x", 3204 log_dst_mac_addr[0], log_dst_mac_addr[1], log_dst_mac_addr[2], 3205 log_dst_mac_addr[3], log_dst_mac_addr[4], log_dst_mac_addr[5]); 3206 cli_out("\n source mac : 0x%02x:%02x:%02x:%02x:%02x:%02x", 3207 log_src_mac_addr[0], log_src_mac_addr[1], log_src_mac_addr[2], 3208 log_src_mac_addr[3], log_src_mac_addr[4], log_src_mac_addr[5]); 3209 cli_out("\n Destination IP : 0x%08x", log_dst_ip_addr); 3210 cli_out("\n source IP : 0x%08x", log_src_ip_addr); 3211 cli_out("\n tpid : 0x%04x", log_tpid); 3212 cli_out("\n vlan id : 0x%04x", log_vid); 3213 cli_out("\n TTL : %u", log_ttl); 3214 cli_out("\n port number : %u", log_port); 3215 cli_out("\n --------------------------------------- \n"); 3216 } 3217 } 3218 } 3219 3220 return diag_set_debug(unit, stack_id, clock_num, diag_debug_mask[unit][stack_id], diag_log_mask[unit][stack_id]); 3221 } 3222 3223 3224 /* PTP Log */ 3225 #define PTP_LOG_USAGE \ 3226 "PTP Log [[+/-]<option> ...] \n\t" \ 3227 " Set or clear UDP logging options, +option adds to list of output, \n\t" \ 3228 " -option removes from list, no +/- toggles current state. \n\t" \ 3229 " If no options given, a current list is printed out.\n" 3230 3231 3232 3233 STATIC cmd_result_t 3234 cmd_ptp_log(int unit, args_t *a) 3235 { 3236 const char * arg; 3237 int stack_id = 0; 3238 int clock_num = 0; 3239 uint32 upper_mask = COMPILER_64_HI(diag_log_mask[unit][stack_id]); 3240 uint32 lower_mask = COMPILER_64_LO(diag_log_mask[unit][stack_id]); 3241 3242 parse_pm_t lower_opt_list[] = { 3243 { "@Log_All", 0xffffffff }, 3244 { "Log_Debug", 0x00000001 }, 3245 { "Log_PDV", 0x00000002 }, 3246 { "Log_Timestamps", 0x00000004 }, 3247 { "Log_PKT_In", 0x00000008 }, 3248 { "Log_PKT_Out", 0x00000010 }, 3249 { "Log_Gpio_DPLL", 0x00000020 }, 3250 { "Log_Synth_DPLL", 0x00000040 }, 3251 { "Log_SyncE_DPLL", 0x00000080 }, 3252 { "Log_CTDEV", 0x00000100 }, 3253 { "Log_FreqPhase", 0x00000200 }, 3254 /* ... */ 3255 3256 { "Log_Scratch", 0x00000000 }, 3257 { 0, 0} 3258 }; 3259 parse_pm_t upper_opt_list[] = { 3260 { "@Log_All", 0xffffffff }, 3261 { "Log_Debug", 0x00000000 }, 3262 { "Log_PDV", 0x00000000 }, 3263 { "Log_Timestamps", 0x00000000 }, 3264 { "Log_PKT_In", 0x00000000 }, 3265 { "Log_PKT_Out", 0x00000000 }, 3266 { "Log_Gpio_DPLL", 0x00000000 }, 3267 { "Log_Synth_DPLL", 0x00000000 }, 3268 { "Log_SyncE_DPLL", 0x00000000 }, 3269 { "Log_CTDEV", 0x00000000 }, 3270 { "Log_FreqPhase", 0x00000000 }, 3271 /* ... */ 3272 { "Log_Scratch", 0x80000000 }, 3273 { 0, 0} 3274 }; 3275 3276 /* In future, when multiple stacks/clocks are in use, ARG_CUR() */ 3277 /* can be used to peek for a "Stack=" or "Clock=" argument */ 3278 3279 if (ARG_CNT(a) == 0) { 3280 cli_out("Logging is enabled for:\n\n"); 3281 parse_mask_format(50, lower_opt_list, lower_mask); 3282 parse_mask_format(50, upper_opt_list, upper_mask); 3283 cli_out("Debugging is disabled for:\n\n"); 3284 parse_mask_format(50, lower_opt_list, ~lower_mask); 3285 parse_mask_format(50, upper_opt_list, ~upper_mask); 3286 cli_out("\n"); 3287 cli_out("Other permissible options: Log_All\n"); 3288 PTP_CLI_RESULT_RETURN(CMD_OK); 3289 } 3290 3291 while ((arg = ARG_GET(a)) != NULL) { 3292 if (parse_mask(arg, lower_opt_list, &lower_mask) || 3293 parse_mask(arg, upper_opt_list, &upper_mask)) { 3294 cli_out("debug: unknown option: %s\n", arg); 3295 PTP_CLI_RESULT_RETURN(CMD_FAIL); 3296 } 3297 } 3298 3299 COMPILER_64_SET(diag_log_mask[unit][stack_id], upper_mask, lower_mask); 3300 3301 return diag_set_debug(unit, stack_id, clock_num, diag_debug_mask[unit][stack_id], diag_log_mask[unit][stack_id]); 3302 } 3303 3304 3305 /* PTP Servo */ 3306 3307 /* We divide the string because pedantic compiler doesn't allow strings longer then 509 characters */ 3308 #define PTP_SERVO_SET_USAGE \ 3309 "\t PTP SerVO SET Frequency Correction=<corr_ppt> Offset=<offset_ppt>\n" \ 3310 "\t PTP SerVO SET PhaseHoldover [UseFixed=<y/n>] [DeltaOffset=<offset>] [FixedOffset=<offset>] [SLEWrate=<slew>] [SYNCoffset=<offset>]\n" 3311 3312 #define PTP_SERVO_USAGE_1 \ 3313 "PTP SerVO <subcommand> [<stack_id>] [<clock_num>] [...]\n" \ 3314 "\t PTP SerVO SHOW Basic servo status\n" \ 3315 "\t PTP SerVO SHOW IPDV Shows IPDV metrics\n" \ 3316 "\t PTP SerVO SHOW PERFormance Shows performance metrics\n" \ 3317 "\t PTP SerVO SHOW PhaseHoldover\n" \ 3318 "\t PTP SerVO SHOW Frequency\n" \ 3319 "\t PTP SerVO CONFig OSCillator_type=\"OCXO\"/\"MINIocxo\" [SERVo=\"EXTernal\"/\"BroadCoM\"]\n" \ 3320 "\t [TRANSport_mode=<transport>] [FreqCorr=<offset_ppt>] [FreqCorrTS=<offset_sec>]\n" 3321 #define PTP_SERVO_USAGE_2 \ 3322 "\t [PhaseOnly=N/y] [FreeRun=N/y]\n" \ 3323 "\t Set/show servo configuration. <transport>: ETHernet, SLOWethernet, HIGHJITter\n" \ 3324 "\t PTP SerVO CLEAR PERFormance Clears performance metrics\n" \ 3325 PTP_SERVO_SET_USAGE 3326 #define PTP_SERVO_USAGE_3 \ 3327 "\t PTP SerVO IPDVCONFig [ObservationInterval=<intv>] [Threshold=<thresh>] [PacingFactor=<pf>]\n" \ 3328 "\t Set/show IPDV configuration\n" \ 3329 "\t PTP SerVO TESTmode <n> Configures servo for test.\n" 3330 3331 STATIC cmd_result_t 3332 cmd_ptp_servo_status_get(int unit, args_t *a) 3333 { 3334 parse_table_t pt; 3335 bcm_ptp_stack_id_t arg_stack_id = PTP_STACK_ID_DEFAULT; 3336 int arg_clock_num = PTP_CLOCK_NUMBER_DEFAULT; 3337 3338 bcm_ptp_servo_status_t status; 3339 3340 parse_table_init(unit, &pt); 3341 parse_table_add(&pt, "Stack_id", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, &arg_stack_id, NULL); 3342 parse_table_add(&pt, "Clock_num", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, &arg_clock_num, NULL); 3343 if (parse_arg_eq(a, &pt) < 0) { 3344 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 3345 } 3346 3347 PTP_IF_ERROR_RETURN(bcm_ptp_servo_status_get(unit, arg_stack_id, arg_clock_num, &status)); 3348 3349 cli_out("\n"); 3350 cli_out("PTP Servo Status\n"); 3351 cli_out("Unit : %d\n", unit); 3352 cli_out("Stack : %d\n", arg_stack_id); 3353 cli_out("Clock : %d\n", arg_clock_num); 3354 cli_out("--------------------------------------------------------------------------------\n"); 3355 cli_out("\t Servo State : %u", (unsigned)status.servo_state); 3356 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 3357 cli_out(" (%s)\n", diag_servo_state_description(status.servo_state)); 3358 #else 3359 switch (status.servo_state) { 3360 case bcmPTPFLLStateAcquiring : 3361 cli_out(" (Acquiring Lock)\n"); 3362 break; 3363 case bcmPTPFLLStateWarmup : 3364 cli_out(" (Warmup)\n"); 3365 break; 3366 case bcmPTPFLLStateFastLoop : 3367 cli_out(" (Fast Loop)\n"); 3368 break; 3369 case bcmPTPFLLStateNormal : 3370 cli_out(" (Normal Loop)\n"); 3371 break; 3372 case bcmPTPFLLStateBridge : 3373 cli_out(" (Bridge)\n"); 3374 break; 3375 case bcmPTPFLLStateHoldover : 3376 cli_out(" (Holdover)\n"); 3377 break; 3378 default : 3379 cli_out(" (Unknown)\n"); 3380 } 3381 #endif 3382 cli_out("\t Servo State Duration : %u (sec)\n", status.servo_state_dur); 3383 cli_out("\t Lock Status : %u (%s)\n", (unsigned)status.lock_status, 3384 diag_servo_lock_status_description(status.lock_status)); 3385 cli_out("--------------------------------------------------------------------------------\n"); 3386 cli_out("\n"); 3387 3388 PTP_CLI_RESULT_RETURN(CMD_OK); 3389 } 3390 3391 3392 STATIC cmd_result_t 3393 cmd_ptp_servo_ipdv_perf_get(int unit, args_t *a) 3394 { 3395 parse_table_t pt; 3396 bcm_ptp_stack_id_t arg_stack_id = PTP_STACK_ID_DEFAULT; 3397 int arg_clock_num = PTP_CLOCK_NUMBER_DEFAULT; 3398 3399 _bcm_ptp_ipdv_performance_t perf; 3400 parse_table_init(unit, &pt); 3401 parse_table_add(&pt, "Stack_id", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, &arg_stack_id, NULL); 3402 parse_table_add(&pt, "Clock_num", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, &arg_clock_num, NULL); 3403 if (parse_arg_eq(a, &pt) < 0) { 3404 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 3405 } 3406 3407 PTP_IF_ERROR_RETURN(_bcm_ptp_servo_ipdv_performance_get(unit, arg_stack_id, arg_clock_num, &perf)); 3408 3409 cli_out("\n"); 3410 cli_out("PTP Servo IPDV Performance Data / Metrics\n"); 3411 cli_out("Unit : %d\n", unit); 3412 cli_out("Stack : %d\n", arg_stack_id); 3413 cli_out("Clock : %d\n", arg_clock_num); 3414 cli_out("--------------------------------------------------------------------------------\n"); 3415 3416 #ifdef COMPILER_HAS_LONGLONG 3417 { 3418 uint64 decval; 3419 unsigned decfrac; 3420 3421 decval = perf.fwd_pct / (uint64)PTP_SERVO_FWD_IPDVPCT_FIXEDPOINT_SCALEFACTOR; 3422 decfrac = perf.fwd_pct - (decval * (uint64)PTP_SERVO_FWD_IPDVPCT_FIXEDPOINT_SCALEFACTOR); 3423 cli_out("\t Forward IPDV %% Below Threshold : %llu.%03u\n", (long long unsigned)decval, decfrac); 3424 3425 decval = perf.fwd_max / (uint64)PTP_SERVO_FWD_IPDVMAX_FIXEDPOINT_SCALEFACTOR; 3426 decfrac = perf.fwd_max - (decval * (uint64)PTP_SERVO_FWD_IPDVMAX_FIXEDPOINT_SCALEFACTOR); 3427 cli_out("\t Forward Maximum IPDV : %llu.%03u (usec)\n", (long long unsigned)decval, decfrac); 3428 3429 decval = perf.fwd_jitter / (uint64)PTP_SERVO_FWD_INTERPKT_JITTER_FIXEDPOINT_SCALEFACTOR; 3430 decfrac = perf.fwd_jitter - (decval * (uint64)PTP_SERVO_FWD_INTERPKT_JITTER_FIXEDPOINT_SCALEFACTOR); 3431 cli_out("\t Forward Interpacket Jitter : %llu.%03u (usec)\n", (long long unsigned)decval, decfrac); 3432 3433 decval = perf.rev_pct / (uint64)PTP_SERVO_REV_IPDVPCT_FIXEDPOINT_SCALEFACTOR; 3434 decfrac = perf.rev_pct - (decval * (uint64)PTP_SERVO_REV_IPDVPCT_FIXEDPOINT_SCALEFACTOR); 3435 cli_out("\t Reverse IPDV %% Below Threshold : %llu.%03u\n", (long long unsigned)decval, decfrac); 3436 3437 decval = perf.rev_max / (uint64)PTP_SERVO_REV_IPDVMAX_FIXEDPOINT_SCALEFACTOR; 3438 decfrac = perf.rev_max - (decval * (uint64)PTP_SERVO_REV_IPDVMAX_FIXEDPOINT_SCALEFACTOR); 3439 cli_out("\t Reverse Maximum IPDV : %llu.%03u (usec)\n", (long long unsigned)decval, decfrac); 3440 3441 decval = perf.rev_jitter / (uint64)PTP_SERVO_REV_INTERPKT_JITTER_FIXEDPOINT_SCALEFACTOR; 3442 decfrac = perf.rev_jitter - (decval * (uint64)PTP_SERVO_REV_INTERPKT_JITTER_FIXEDPOINT_SCALEFACTOR); 3443 cli_out("\t Reverse Interpacket Jitter : %llu.%03u (usec)\n", (long long unsigned)decval, decfrac); 3444 } 3445 #endif /* COMPILER_HAS_LONGLONG */ 3446 cli_out("--------------------------------------------------------------------------------\n"); 3447 cli_out("\n"); 3448 3449 PTP_CLI_RESULT_RETURN(CMD_OK); 3450 } 3451 3452 3453 STATIC cmd_result_t 3454 cmd_ptp_servo_perf_get(int unit, args_t *a) 3455 { 3456 parse_table_t pt; 3457 bcm_ptp_stack_id_t arg_stack_id = PTP_STACK_ID_DEFAULT; 3458 int arg_clock_num = PTP_CLOCK_NUMBER_DEFAULT; 3459 bcm_ptp_servo_config_t config; 3460 _bcm_ptp_servo_performance_t perf; 3461 3462 PTP_IF_ERROR_RETURN(bcm_ptp_servo_configuration_get(unit, arg_stack_id, arg_clock_num, &config)); 3463 3464 parse_table_init(unit, &pt); 3465 parse_table_add(&pt, "Stack_id", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, &arg_stack_id, NULL); 3466 parse_table_add(&pt, "Clock_num", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, &arg_clock_num, NULL); 3467 if (parse_arg_eq(a, &pt) < 0) { 3468 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 3469 } 3470 3471 PTP_IF_ERROR_RETURN(_bcm_ptp_servo_performance_get(unit, arg_stack_id, arg_clock_num, &perf)); 3472 3473 cli_out("\n"); 3474 cli_out("PTP Servo Performance Data / Metrics\n"); 3475 cli_out("Unit : %d\n", unit); 3476 cli_out("Stack : %d\n", arg_stack_id); 3477 cli_out("Clock : %d\n", arg_clock_num); 3478 cli_out("--------------------------------------------------------------------------------\n"); 3479 cli_out("\t Servo State : %u", (unsigned)perf.status.servo_state); 3480 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 3481 cli_out(" (%s)\n", diag_servo_state_description(perf.status.servo_state)); 3482 #else 3483 switch (perf.status.servo_state) { 3484 case bcmPTPFLLStateAcquiring : 3485 cli_out(" (Acquiring Lock)\n"); 3486 break; 3487 case bcmPTPFLLStateWarmup : 3488 cli_out(" (Warmup)\n"); 3489 break; 3490 case bcmPTPFLLStateFastLoop : 3491 cli_out(" (Fast Loop)\n"); 3492 break; 3493 case bcmPTPFLLStateNormal : 3494 cli_out(" (Normal Loop)\n"); 3495 break; 3496 case bcmPTPFLLStateBridge : 3497 cli_out(" (Bridge)\n"); 3498 break; 3499 case bcmPTPFLLStateHoldover : 3500 cli_out(" (Holdover)\n"); 3501 break; 3502 default : 3503 cli_out(" (Unknown)\n"); 3504 } 3505 #endif 3506 cli_out("\t Servo State Duration : %u (sec)\n", perf.status.servo_state_dur); 3507 3508 cli_out("\n"); 3509 3510 #ifdef COMPILER_HAS_LONGLONG 3511 { 3512 int64 decval; 3513 unsigned decfrac; 3514 #ifndef BCM_PTP_EXT_SERVO_SUPPORT 3515 uint64 decval_; 3516 3517 if (config.servo == bcmPTPServoTypeExt) 3518 { 3519 decval_ = perf.fwd_weight / 3520 (uint64)PTP_SERVO_FWD_FLOW_WEIGHT_FIXEDPOINT_SCALEFACTOR; 3521 decfrac = perf.fwd_weight - 3522 (decval_ * (uint64)PTP_SERVO_FWD_FLOW_WEIGHT_FIXEDPOINT_SCALEFACTOR); 3523 cli_out("\t Forward Flow Weight : %llu.%03u\n", (long long unsigned)decval_, decfrac); 3524 3525 cli_out("\t Forward Flow Transient-Free : %u (900 sec Window)\n", perf.fwd_trans_free_900); 3526 cli_out("\t Forward Flow Transient-Free : %u (3600 sec Window)\n", perf.fwd_trans_free_3600); 3527 3528 decval_ = perf.fwd_pct / 3529 (uint64)PTP_SERVO_FWD_FLOW_TRANSACTIONS_PCT_FIXEDPOINT_SCALEFACTOR; 3530 decfrac = perf.fwd_pct - 3531 (decval_ * (uint64)PTP_SERVO_FWD_FLOW_TRANSACTIONS_PCT_FIXEDPOINT_SCALEFACTOR); 3532 cli_out("\t Forward Flow Transactions Used : %llu.%03u (%%)\n", (long long unsigned)decval_, decfrac); 3533 3534 if (perf.fwd_min_Tdev == (uint64) -1) { 3535 cli_out("\t Forward Flow Oper. Min TDEV : n/a (nsec)\n"); 3536 } else { 3537 decval_ = perf.fwd_min_Tdev / 3538 (uint64)PTP_SERVO_FWD_MIN_TDEV_FIXEDPOINT_SCALEFACTOR; 3539 decfrac = perf.fwd_min_Tdev - 3540 (decval_ * (uint64)PTP_SERVO_FWD_MIN_TDEV_FIXEDPOINT_SCALEFACTOR); 3541 cli_out("\t Forward Flow Oper. Min TDEV : %llu.%03u (nsec)\n", (long long unsigned)decval_, decfrac); 3542 } 3543 decval_ = perf.fwd_Mafie / 3544 (uint64)PTP_SERVO_FWD_MAFIE_FIXEDPOINT_SCALEFACTOR; 3545 decfrac = perf.fwd_Mafie - 3546 (decval_ * (uint64)PTP_SERVO_FWD_MAFIE_FIXEDPOINT_SCALEFACTOR); 3547 cli_out("\t Forward Mafie : %llu.%03u\n", (long long unsigned)decval_, decfrac); 3548 3549 decval_ = perf.fwd_min_cluster_width / 3550 (uint64)PTP_SERVO_FWD_MIN_CLUSTER_WIDTH_FIXEDPOINT_SCALEFACTOR; 3551 decfrac = perf.fwd_min_cluster_width - 3552 (decval_ * (uint64)PTP_SERVO_FWD_MIN_CLUSTER_WIDTH_FIXEDPOINT_SCALEFACTOR); 3553 cli_out("\t Forward Flow Min Cluster Width : %llu.%03u (nsec)\n", (long long unsigned)decval_, decfrac); 3554 3555 decval_ = perf.fwd_mode_width / 3556 (uint64)PTP_SERVO_FWD_MODE_WIDTH_FIXEDPOINT_SCALEFACTOR; 3557 decfrac = perf.fwd_mode_width - 3558 (decval_ * (uint64)PTP_SERVO_FWD_MODE_WIDTH_FIXEDPOINT_SCALEFACTOR); 3559 cli_out("\t Forward Flow Mode Width : %llu.%03u (nsec)\n", (long long unsigned)decval_, decfrac); 3560 3561 cli_out("\n"); 3562 3563 decval_ = perf.rev_weight / 3564 (uint64)PTP_SERVO_REV_FLOW_WEIGHT_FIXEDPOINT_SCALEFACTOR; 3565 decfrac = perf.rev_weight - 3566 (decval_ * (uint64)PTP_SERVO_REV_FLOW_WEIGHT_FIXEDPOINT_SCALEFACTOR); 3567 cli_out("\t Reverse Flow Weight : %llu.%03u\n", (long long unsigned)decval_, decfrac); 3568 3569 cli_out("\t Reverse Flow Transient-Free : %u (900 sec Window)\n", perf.rev_trans_free_900); 3570 cli_out("\t Reverse Flow Transient-Free : %u (3600 sec Window)\n", perf.rev_trans_free_3600); 3571 3572 decval_ = perf.rev_pct / 3573 (uint64)PTP_SERVO_REV_FLOW_TRANSACTIONS_PCT_FIXEDPOINT_SCALEFACTOR; 3574 decfrac = perf.rev_pct - 3575 (decval_ * (uint64)PTP_SERVO_REV_FLOW_TRANSACTIONS_PCT_FIXEDPOINT_SCALEFACTOR); 3576 cli_out("\t Reverse Flow Transactions Used : %llu.%03u (%%)\n", (long long unsigned)decval_, decfrac); 3577 3578 decval_ = perf.rev_min_Tdev / 3579 (uint64)PTP_SERVO_REV_MIN_TDEV_FIXEDPOINT_SCALEFACTOR; 3580 decfrac = perf.rev_min_Tdev - 3581 (decval_ * (uint64)PTP_SERVO_REV_MIN_TDEV_FIXEDPOINT_SCALEFACTOR); 3582 cli_out("\t Reverse Flow Oper. Min TDEV : %llu.%03u (nsec)\n", (long long unsigned)decval_, decfrac); 3583 3584 decval_ = perf.rev_Mafie / 3585 (uint64)PTP_SERVO_REV_MAFIE_FIXEDPOINT_SCALEFACTOR; 3586 decfrac = perf.rev_Mafie - 3587 (decval_ * (uint64)PTP_SERVO_REV_MAFIE_FIXEDPOINT_SCALEFACTOR); 3588 cli_out("\t Reverse Mafie : %llu.%03u\n", (long long unsigned)decval_, decfrac); 3589 3590 decval_ = perf.rev_min_cluster_width / 3591 (uint64)PTP_SERVO_REV_MIN_CLUSTER_WIDTH_FIXEDPOINT_SCALEFACTOR; 3592 decfrac = perf.rev_min_cluster_width - 3593 (decval_ * (uint64)PTP_SERVO_REV_MIN_CLUSTER_WIDTH_FIXEDPOINT_SCALEFACTOR); 3594 cli_out("\t Reverse Flow Min Cluster Width : %llu.%03u (nsec)\n", (long long unsigned)decval_, decfrac); 3595 3596 decval_ = perf.rev_mode_width / 3597 (uint64)PTP_SERVO_REV_MODE_WIDTH_FIXEDPOINT_SCALEFACTOR; 3598 decfrac = perf.rev_mode_width - 3599 (decval_ * (uint64)PTP_SERVO_REV_MODE_WIDTH_FIXEDPOINT_SCALEFACTOR); 3600 cli_out("\t Reverse Flow Mode Width : %llu.%03u (nsec)\n", (long long unsigned)decval_, decfrac); 3601 3602 cli_out("\n"); 3603 } 3604 #endif 3605 decval = perf.freq_correction / 3606 (int64)PTP_SERVO_FREQ_CORRECTION_FIXEDPOINT_SCALEFACTOR; 3607 decfrac = (decval >= 0) ? 3608 (perf.freq_correction - 3609 (decval * (int64)PTP_SERVO_FREQ_CORRECTION_FIXEDPOINT_SCALEFACTOR)) : 3610 ((decval * (int64)PTP_SERVO_FREQ_CORRECTION_FIXEDPOINT_SCALEFACTOR) - 3611 perf.freq_correction); 3612 cli_out("\t Frequency Correction : %lld.%03u (ppb)\n", (long long)decval, decfrac); 3613 3614 decval = perf.phase_correction / 3615 (int64)PTP_SERVO_PHASE_CORRECTION_FIXEDPOINT_SCALEFACTOR; 3616 decfrac = (decval >= 0) ? 3617 (perf.phase_correction - 3618 (decval * (int64)PTP_SERVO_PHASE_CORRECTION_FIXEDPOINT_SCALEFACTOR)) : 3619 ((decval * (int64)PTP_SERVO_PHASE_CORRECTION_FIXEDPOINT_SCALEFACTOR) - 3620 perf.phase_correction); 3621 cli_out("\t Phase Correction : %lld.%03u (ppb)\n", (long long)decval, decfrac); 3622 3623 cli_out("\n"); 3624 3625 #ifndef BCM_PTP_EXT_SERVO_SUPPORT 3626 if (config.servo == bcmPTPServoTypeExt) 3627 { 3628 if (perf.tdev_estimate == (uint64) -1) { 3629 cli_out("\t Output TDEV Estimate : n/a (nsec)\n"); 3630 } else { 3631 decval_ = perf.tdev_estimate / 3632 (uint64)PTP_SERVO_TDEV_ESTIMATE_FIXEDPOINT_SCALEFACTOR; 3633 decfrac = perf.tdev_estimate - 3634 (decval_ * (uint64)PTP_SERVO_TDEV_ESTIMATE_FIXEDPOINT_SCALEFACTOR); 3635 cli_out("\t Output TDEV Estimate : %llu.%03u (nsec)\n", (long long unsigned)decval_, decfrac); 3636 } 3637 3638 if (perf.mdev_estimate == (uint64) -1) { 3639 cli_out("\t Output MDEV Estimate : n/a (ppb)\n"); 3640 } else { 3641 decval_ = perf.mdev_estimate / 3642 (uint64)PTP_SERVO_MDEV_ESTIMATE_FIXEDPOINT_SCALEFACTOR; 3643 decfrac = perf.mdev_estimate - 3644 (decval_ * (uint64)PTP_SERVO_MDEV_ESTIMATE_FIXEDPOINT_SCALEFACTOR); 3645 cli_out("\t Output MDEV Estimate : %llu.%03u (ppb)\n", (long long unsigned)decval_, decfrac); 3646 } 3647 3648 cli_out("\n"); 3649 } 3650 decval = perf.residual_phase_error / 3651 (int64)PTP_SERVO_RESIDUAL_PHASE_ERROR_FIXEDPOINT_SCALEFACTOR; 3652 decfrac = (decval >= 0) ? 3653 (perf.residual_phase_error - 3654 (decval * (int64)PTP_SERVO_RESIDUAL_PHASE_ERROR_FIXEDPOINT_SCALEFACTOR)) : 3655 ((decval * (int64)PTP_SERVO_RESIDUAL_PHASE_ERROR_FIXEDPOINT_SCALEFACTOR) - 3656 perf.residual_phase_error); 3657 cli_out("\t Residual Phase Error : %lld.%03u (nsec)\n", (long long)decval, decfrac); 3658 3659 decval_ = (int64)perf.min_round_trip_delay / 3660 (int64)PTP_SERVO_MIN_ROUNDTRIP_DELAY_FIXEDPOINT_SCALEFACTOR; 3661 decfrac = (int64)perf.min_round_trip_delay - 3662 (decval_ * (int64)PTP_SERVO_MIN_ROUNDTRIP_DELAY_FIXEDPOINT_SCALEFACTOR); 3663 cli_out("\t Min. Roundtrip Delay : %lld.%03u (nsec)\n", (long long)decval_, decfrac); 3664 #endif 3665 3666 cli_out("\n"); 3667 3668 cli_out("\t Sync Packet Rate : %u (pkts/sec)\n", perf.fwd_pkt_rate); 3669 cli_out("\t Delay Packet Rate : %u (pkts/sec)\n", perf.rev_pkt_rate); 3670 3671 cli_out("\n"); 3672 3673 #ifndef BCM_PTP_EXT_SERVO_SUPPORT 3674 if (config.servo == bcmPTPServoTypeExt) 3675 { 3676 decval_ = perf.ipdv_data.fwd_pct / 3677 (uint64)PTP_SERVO_FWD_IPDVPCT_FIXEDPOINT_SCALEFACTOR; 3678 decfrac = perf.ipdv_data.fwd_pct - 3679 (decval_ * (uint64)PTP_SERVO_FWD_IPDVPCT_FIXEDPOINT_SCALEFACTOR); 3680 cli_out("\t Forward IPDV %% Below Threshold : %llu.%03u\n", (long long unsigned)decval_, decfrac); 3681 3682 decval_ = perf.ipdv_data.fwd_max / 3683 (uint64)PTP_SERVO_FWD_IPDVMAX_FIXEDPOINT_SCALEFACTOR; 3684 decfrac = perf.ipdv_data.fwd_max - 3685 (decval_ * (uint64)PTP_SERVO_FWD_IPDVMAX_FIXEDPOINT_SCALEFACTOR); 3686 cli_out("\t Forward Maximum IPDV : %llu.%03u (usec)\n", (long long unsigned)decval_, decfrac); 3687 3688 decval_ = perf.ipdv_data.fwd_jitter / (uint64)PTP_SERVO_FWD_INTERPKT_JITTER_FIXEDPOINT_SCALEFACTOR; 3689 decfrac = perf.ipdv_data.fwd_jitter - 3690 (decval_ * (uint64)PTP_SERVO_FWD_INTERPKT_JITTER_FIXEDPOINT_SCALEFACTOR); 3691 cli_out("\t Forward Interpacket Jitter : %llu.%03u (usec)\n", (long long unsigned)decval_, decfrac); 3692 3693 cli_out("\n"); 3694 3695 decval_ = perf.ipdv_data.rev_pct / (uint64)PTP_SERVO_REV_IPDVPCT_FIXEDPOINT_SCALEFACTOR; 3696 decfrac = perf.ipdv_data.rev_pct - (decval_ * (uint64)PTP_SERVO_REV_IPDVPCT_FIXEDPOINT_SCALEFACTOR); 3697 cli_out("\t Reverse IPDV %% Below Threshold : %llu.%03u\n", (long long unsigned)decval_, decfrac); 3698 3699 decval_ = perf.ipdv_data.rev_max / (uint64)PTP_SERVO_REV_IPDVMAX_FIXEDPOINT_SCALEFACTOR; 3700 decfrac = perf.ipdv_data.rev_max - (decval_ * (uint64)PTP_SERVO_REV_IPDVMAX_FIXEDPOINT_SCALEFACTOR); 3701 cli_out("\t Reverse Maximum IPDV : %llu.%03u (usec)\n", (long long unsigned)decval_, decfrac); 3702 3703 decval_ = perf.ipdv_data.rev_jitter / (uint64)PTP_SERVO_REV_INTERPKT_JITTER_FIXEDPOINT_SCALEFACTOR; 3704 decfrac = perf.ipdv_data.rev_jitter - (decval_ * (uint64)PTP_SERVO_REV_INTERPKT_JITTER_FIXEDPOINT_SCALEFACTOR); 3705 cli_out("\t Reverse Interpacket Jitter : %llu.%03u (usec)\n", (long long unsigned)decval_, decfrac); 3706 } 3707 #endif 3708 } 3709 #endif /* COMPILER_HAS_LONGLONG */ 3710 cli_out("--------------------------------------------------------------------------------\n"); 3711 cli_out("\n"); 3712 3713 PTP_CLI_RESULT_RETURN(CMD_OK); 3714 } 3715 3716 STATIC cmd_result_t 3717 cmd_ptp_servo_perf_clear(int unit, args_t *a) 3718 { 3719 parse_table_t pt; 3720 bcm_ptp_stack_id_t arg_stack_id = PTP_STACK_ID_DEFAULT; 3721 int arg_clock_num = PTP_CLOCK_NUMBER_DEFAULT; 3722 3723 parse_table_init(unit, &pt); 3724 parse_table_add(&pt, "Stack_id", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, &arg_stack_id, NULL); 3725 parse_table_add(&pt, "Clock_num", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, &arg_clock_num, NULL); 3726 if (parse_arg_eq(a, &pt) < 0) { 3727 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 3728 } 3729 3730 PTP_IF_ERROR_RETURN(_bcm_ptp_servo_performance_data_clear(unit, arg_stack_id, arg_clock_num)); 3731 3732 PTP_CLI_RESULT_RETURN(CMD_OK); 3733 } 3734 3735 3736 STATIC cmd_result_t 3737 cmd_ptp_servo_ipdv_config_show(int unit, bcm_ptp_stack_id_t stack_id, int clock_num) 3738 { 3739 _bcm_ptp_ipdv_config_t config; 3740 3741 PTP_IF_ERROR_RETURN(_bcm_ptp_servo_ipdv_configuration_get(unit, stack_id, clock_num, &config)); 3742 3743 cli_out("\n"); 3744 cli_out("PTP Servo IPDV Configuration\n"); 3745 cli_out("Unit : %d\n", unit); 3746 cli_out("Stack : %d\n", stack_id); 3747 cli_out("Clock : %d\n", clock_num); 3748 cli_out("--------------------------------------------------------------------------------\n"); 3749 cli_out("\t Observation Interval : %u\n", config.observation_interval); 3750 cli_out("\t Threshold : %d (nsec)\n", config.threshold); 3751 cli_out("\t Pacing Factor : %u\n", config.pacing_factor); 3752 cli_out("--------------------------------------------------------------------------------\n"); 3753 cli_out("\n"); 3754 3755 PTP_CLI_RESULT_RETURN(CMD_OK); 3756 } 3757 3758 3759 STATIC cmd_result_t 3760 cmd_ptp_servo_ipdv_config(int unit, args_t *a) 3761 { 3762 parse_table_t pt; 3763 bcm_ptp_stack_id_t arg_stack_id = PTP_STACK_ID_DEFAULT; 3764 int arg_clock_num = PTP_CLOCK_NUMBER_DEFAULT; 3765 int invalid_value = 0x7fffffff; 3766 int arg_obs_interval = 1; 3767 int arg_threshold = 50; 3768 int arg_pacing_factor = 16; 3769 int perform_set = 0; 3770 3771 _bcm_ptp_ipdv_config_t config; 3772 sal_memset(&config, 0, sizeof(_bcm_ptp_ipdv_config_t)); 3773 3774 parse_table_init(unit, &pt); 3775 parse_table_add(&pt, "Stack_id", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, &arg_stack_id, NULL); 3776 parse_table_add(&pt, "Clock_num", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, &arg_clock_num, NULL); 3777 parse_table_add(&pt, "ObservationInterval", PQ_INT, (void*)(size_t)invalid_value, &arg_obs_interval, NULL); 3778 parse_table_add(&pt, "Threshold", PQ_INT, (void*)(size_t)invalid_value, &arg_threshold, NULL); 3779 parse_table_add(&pt, "PacingFactor", PQ_INT, (void*)(size_t)invalid_value, &arg_pacing_factor, NULL); 3780 if (parse_arg_eq(a, &pt) < 0) { 3781 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 3782 } 3783 parse_arg_eq_done(&pt); 3784 3785 if (arg_obs_interval != invalid_value) { 3786 config.observation_interval = (uint16)arg_obs_interval; 3787 perform_set = 1; 3788 } 3789 if (arg_threshold != invalid_value) { 3790 config.threshold = (int32)arg_threshold; 3791 perform_set = 1; 3792 } 3793 if (arg_pacing_factor != invalid_value) { 3794 config.pacing_factor = (uint16)arg_pacing_factor; 3795 perform_set = 1; 3796 } 3797 3798 if (perform_set) { 3799 PTP_IF_ERROR_RETURN(_bcm_ptp_servo_ipdv_configuration_set(unit, arg_stack_id, arg_clock_num, config)); 3800 } 3801 3802 return cmd_ptp_servo_ipdv_config_show(unit, arg_stack_id, arg_clock_num); 3803 } 3804 3805 3806 STATIC cmd_result_t 3807 cmd_ptp_servo_phase_holdover_get(int unit, args_t *a) 3808 { 3809 bcm_ptp_phase_holdover_state_t state; 3810 3811 PTP_IF_ERROR_RETURN(_bcm_ptp_phase_holdover_get(unit, PTP_STACK_ID_DEFAULT, PTP_CLOCK_NUMBER_DEFAULT, &state)); 3812 3813 #ifdef COMPILER_HAS_LONGLONG 3814 cli_out("\n"); 3815 cli_out("PTP Servo Phase Holdover State:\n"); 3816 cli_out(" Reported Phase Offset: %12lld ns\n", (long long)state.reported_phase_offset); 3817 cli_out(" Delta Phase Offset : %12lld ns\n", (long long)state.delta_phase_offset); 3818 cli_out(" Fixed Phase Offset : %12lld ns\n", (long long)state.fixed_phase_offset); 3819 cli_out(" Using Fixed Offset : %12s\n", (state.use_fixed_phase_offset) ? "Yes" : "No"); 3820 cli_out(" Phase Slew Rate : %12d ppb\n", (int)state.phase_slew_rate_ppb); 3821 cli_out(" Sync Phase Offset : %12u ns\n", (unsigned)state.sync_phase_offset_ns); 3822 #endif /* COMPILER_HAS_LONGLONG */ 3823 3824 PTP_CLI_RESULT_RETURN(CMD_OK); 3825 } 3826 3827 STATIC cmd_result_t 3828 cmd_ptp_servo_phase_holdover_set(int unit, args_t *a) 3829 { 3830 parse_table_t pt; 3831 bcm_ptp_phase_holdover_state_t state; 3832 3833 PTP_IF_ERROR_RETURN(_bcm_ptp_phase_holdover_get(unit, PTP_STACK_ID_DEFAULT, PTP_CLOCK_NUMBER_DEFAULT, &state)); 3834 3835 parse_table_init(unit, &pt); 3836 parse_table_add(&pt, "UseFixed", PQ_BOOL, NULL, &state.use_fixed_phase_offset, NULL); 3837 parse_table_add(&pt, "DeltaOffset", PQ_DFL|PQ_INT64, NULL, &state.delta_phase_offset, NULL); 3838 parse_table_add(&pt, "FixedOffset", PQ_DFL|PQ_INT64, NULL, &state.fixed_phase_offset, NULL); 3839 parse_table_add(&pt, "SLEWrate", PQ_INT, NULL, &state.phase_slew_rate_ppb, NULL); 3840 parse_table_add(&pt, "SYNCoffset", PQ_INT, NULL, &state.sync_phase_offset_ns, NULL); 3841 3842 if (parse_arg_eq(a, &pt) < 0) { 3843 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 3844 } 3845 parse_arg_eq_done(&pt); 3846 3847 PTP_IF_ERROR_RETURN(_bcm_ptp_phase_holdover_set(unit, PTP_STACK_ID_DEFAULT, PTP_CLOCK_NUMBER_DEFAULT, &state)); 3848 3849 PTP_CLI_RESULT_RETURN(CMD_OK); 3850 } 3851 3852 STATIC cmd_result_t 3853 cmd_ptp_servo_freq_corr_get(int unit, args_t *a) 3854 { 3855 int32 corr = 0, offset = 0; 3856 3857 PTP_IF_ERROR_RETURN(_bcm_ptp_freq_corr_get(unit, PTP_STACK_ID_DEFAULT, PTP_CLOCK_NUMBER_DEFAULT, &corr, &offset)); 3858 3859 cli_out(" Servo Frequency Correction: %d ppt Offset: %d ppt\n", 3860 corr, offset); 3861 3862 PTP_CLI_RESULT_RETURN(CMD_OK); 3863 } 3864 3865 STATIC cmd_result_t 3866 cmd_ptp_servo_freq_corr_set(int unit, args_t *a) 3867 { 3868 parse_table_t pt; 3869 int32 corr = 0, offset = 0; 3870 3871 parse_table_init(unit, &pt); 3872 parse_table_add(&pt, "Correction", PQ_INT, NULL, &corr, NULL); 3873 parse_table_add(&pt, "Offset", PQ_INT, NULL, &offset, NULL); 3874 3875 if (parse_arg_eq(a, &pt) < 0) { 3876 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 3877 cli_out(PTP_SERVO_SET_USAGE); 3878 PTP_CLI_RESULT_RETURN(CMD_FAIL); 3879 } 3880 parse_arg_eq_done(&pt); 3881 3882 PTP_IF_ERROR_RETURN(_bcm_ptp_freq_corr_set(unit, PTP_STACK_ID_DEFAULT, PTP_CLOCK_NUMBER_DEFAULT, corr, offset)); 3883 3884 PTP_CLI_RESULT_RETURN(CMD_OK); 3885 } 3886 3887 STATIC cmd_result_t 3888 cmd_ptp_servo_config_show(int unit, bcm_ptp_stack_id_t stack_id, int clock_num) 3889 { 3890 bcm_ptp_servo_config_t config; 3891 int decval; 3892 unsigned decfrac; 3893 char uint64_decimal_string[27]; 3894 3895 PTP_IF_ERROR_RETURN(bcm_ptp_servo_configuration_get(unit, stack_id, clock_num, &config)); 3896 3897 cli_out("\n"); 3898 cli_out("PTP Servo Configuration\n"); 3899 cli_out("Unit : %d\n", unit); 3900 cli_out("Stack : %d\n", stack_id); 3901 cli_out("Clock : %d\n", clock_num); 3902 cli_out("--------------------------------------------------------------------------------\n"); 3903 3904 cli_out("\t Servo Type : "); 3905 switch (config.servo) { 3906 case bcmPTPServoTypeExt: 3907 cli_out("External, "); 3908 break; 3909 case bcmPTPServoTypeBCM: 3910 cli_out("Broadcom, "); 3911 break; 3912 default: 3913 cli_out(" <%02d> ", (config.servo)); 3914 break; 3915 } 3916 if (config.flags & BCM_PTP_SERVO_PHASE_ONLY) { 3917 cli_out(" Phase only\n"); 3918 } else { 3919 cli_out(" Freq + Phase\n"); 3920 } 3921 3922 cli_out("\t Phase holdover mode : "); 3923 if (config.flags & BCM_PTP_SERVO_PHASE_HOLDOVER) { 3924 cli_out("Enabled\n"); 3925 } else { 3926 cli_out("Not enabled\n"); 3927 } 3928 3929 if (config.flags & BCM_PTP_SERVO_LOCK_SWITCH_FREQ) { 3930 cli_out("\t TOP frequency assumed locked to switch freq\n"); 3931 } 3932 if (config.flags & BCM_PTP_SERVO_IGNORE_FREQ) { 3933 cli_out("\t Servo frequency corrections being ignored (debug)\n"); 3934 } 3935 3936 cli_out("\t Oscillator Type : %u", (unsigned)config.osc_type); 3937 switch (config.osc_type) { 3938 case bcmPTPOscTypeRB: 3939 cli_out(" (Rubidium)\n"); 3940 break; 3941 case bcmPTPOscTypeDOCXO: 3942 cli_out(" (Double oven OCXO)\n"); 3943 break; 3944 case bcmPTPOscTypeOCXO: 3945 cli_out(" (OCXO)\n"); 3946 break; 3947 case bcmPTPOscTypeMiniOCXO: 3948 cli_out(" (Mini OCXO)\n"); 3949 break; 3950 case bcmPTPOscTypeTCXO: 3951 cli_out(" (TCXO)\n"); 3952 break; 3953 default : 3954 cli_out(" (Unknown)\n"); 3955 } 3956 cli_out("\t PTP Transport Mode : %u", (unsigned)config.transport_mode); 3957 switch (config.transport_mode) { 3958 case bcmPTPTransportModeEthernet : 3959 cli_out(" (Ethernet)\n"); 3960 break; 3961 case bcmPTPTransportModeDSL: 3962 cli_out(" (DSL)\n"); 3963 break; 3964 case bcmPTPTransportModeMicrowave: 3965 cli_out(" (Microwave)\n"); 3966 break; 3967 case bcmPTPTransportModeSONET: 3968 cli_out(" (SONET)\n"); 3969 break; 3970 case bcmPTPTransportModeSlowEthernet: 3971 cli_out(" (Slow Ethernet)\n"); 3972 break; 3973 case bcmPTPTransportModeHighJitter: 3974 cli_out(" (High Jitter)\n"); 3975 break; 3976 default : 3977 cli_out(" (Unknown)\n"); 3978 } 3979 cli_out("\t Phase Mode : %u\n", config.ptp_phase_mode); 3980 3981 decval = config.freq_corr / 3982 PTP_SERVO_OCXO_FREQ_OFFSET_FIXEDPOINT_SCALEFACTOR; 3983 decfrac = (decval >= 0) ? 3984 (config.freq_corr - 3985 (decval * PTP_SERVO_OCXO_FREQ_OFFSET_FIXEDPOINT_SCALEFACTOR)) : 3986 ((decval * PTP_SERVO_OCXO_FREQ_OFFSET_FIXEDPOINT_SCALEFACTOR) - 3987 config.freq_corr); 3988 cli_out("\t Freq. Correction : %d (%d.%03u ppb)\n", config.freq_corr, decval, decfrac); 3989 format_uint64_decimal(uint64_decimal_string, config.freq_corr_time.seconds, ','); 3990 cli_out("\t Freq. Correction Timestamp : %s.%09u sec.\n", 3991 uint64_decimal_string, config.freq_corr_time.nanoseconds); 3992 3993 cli_out("\t Bridge Time : %u\n", config.bridge_time); 3994 cli_out("--------------------------------------------------------------------------------\n"); 3995 cli_out("\n"); 3996 3997 PTP_CLI_RESULT_RETURN(CMD_OK); 3998 } 3999 4000 4001 STATIC cmd_result_t 4002 cmd_ptp_servo_config(int unit, args_t *a) 4003 { 4004 parse_table_t pt; 4005 bcm_ptp_stack_id_t arg_stack_id = PTP_STACK_ID_DEFAULT; 4006 int arg_clock_num = PTP_CLOCK_NUMBER_DEFAULT; 4007 int invalid_value = 0x7fffffff; 4008 int arg_freq_corr = 0; 4009 int arg_freq_corr_ts = 0; 4010 int arg_phase_only = 0; 4011 int arg_phaseholdover_mode = 0; 4012 int arg_free_run = 0; 4013 int arg_lock_freq = 0; 4014 int got_set_data = 0; 4015 char * servo_type_str[3] = {"EXTernal", "BroadCoM", 0}; 4016 char * osc_type_str[6] = {"RuBidium", "DOCXO", "OCXO", "MINIocxo", "TCXO", 0}; 4017 char * transport_mode_str[7] = {"ETHernet", "DSL", "MicroWave", "SONET", "SLOWethernet", "HIGHJITter", 0}; 4018 4019 bcm_ptp_servo_config_t config; 4020 4021 config.osc_type = invalid_value; 4022 config.transport_mode = bcmPTPTransportModeEthernet; 4023 config.ptp_phase_mode = 1; 4024 config.freq_corr = 0; 4025 COMPILER_64_SET(config.freq_corr_time.seconds, 0, 0); 4026 config.freq_corr_time.nanoseconds = 0; 4027 config.servo = 0; 4028 config.flags = 0; 4029 config.bridge_time = 300; 4030 4031 parse_table_init(unit, &pt); 4032 parse_table_add(&pt, "Stack_id", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, &arg_stack_id, NULL); 4033 parse_table_add(&pt, "Clock_num", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, &arg_clock_num, NULL); 4034 parse_table_add(&pt, "SERVo", PQ_MULTI | PQ_DFL, 0, &config.servo, servo_type_str); 4035 parse_table_add(&pt, "OSCillator_type", PQ_MULTI | PQ_DFL, 0, &config.osc_type, osc_type_str); 4036 parse_table_add(&pt, "TRANSport_mode", PQ_MULTI | PQ_DFL, 0, &config.transport_mode, transport_mode_str); 4037 parse_table_add(&pt, "FreqCorr", PQ_INT, (void*)(size_t)invalid_value, &arg_freq_corr, NULL); 4038 parse_table_add(&pt, "FreqCorrTS", PQ_INT, (void*)(size_t)invalid_value, &arg_freq_corr_ts, NULL); 4039 parse_table_add(&pt, "PhaseOnly", PQ_BOOL, (void*)(size_t)invalid_value, &arg_phase_only, NULL); 4040 parse_table_add(&pt, "FreeRun", PQ_BOOL, (void*)(size_t)invalid_value, &arg_free_run, NULL); 4041 parse_table_add(&pt, "LockFreq", PQ_BOOL, (void*)(size_t)invalid_value, &arg_lock_freq, NULL); 4042 parse_table_add(&pt, "PhaseHoldovermode", PQ_BOOL, (void*)(size_t)invalid_value, &arg_phaseholdover_mode, NULL); 4043 4044 if (parse_arg_eq(a, &pt) < 0) { 4045 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 4046 parse_arg_eq_done(&pt); 4047 return(CMD_FAIL); 4048 } 4049 4050 parse_arg_eq_done(&pt); 4051 4052 got_set_data = (config.osc_type != invalid_value || arg_freq_corr != invalid_value || arg_freq_corr_ts != invalid_value || 4053 arg_free_run != invalid_value || arg_lock_freq != invalid_value || (arg_phaseholdover_mode != invalid_value)); 4054 4055 if (got_set_data) { 4056 if (config.osc_type == invalid_value) { 4057 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4058 } 4059 if (arg_freq_corr != invalid_value) { 4060 config.freq_corr = arg_freq_corr; 4061 } 4062 if (arg_freq_corr_ts != invalid_value) { 4063 COMPILER_64_SET(config.freq_corr_time.seconds, 0, arg_freq_corr_ts); 4064 } 4065 if (arg_free_run == 1) { 4066 config.flags |= BCM_PTP_SERVO_IGNORE_FREQ; 4067 } 4068 if (arg_lock_freq == 1) { 4069 config.flags |= BCM_PTP_SERVO_LOCK_SWITCH_FREQ; 4070 } 4071 if (arg_phase_only == 1) { 4072 config.flags |= BCM_PTP_SERVO_PHASE_ONLY; 4073 } 4074 if (arg_phaseholdover_mode == 1) { 4075 config.flags |= BCM_PTP_SERVO_PHASE_HOLDOVER; 4076 } 4077 } 4078 4079 if (got_set_data) { 4080 PTP_IF_ERROR_RETURN(bcm_ptp_servo_configuration_set(unit, arg_stack_id, arg_clock_num, &config)); 4081 } 4082 4083 return cmd_ptp_servo_config_show(unit, arg_stack_id, arg_clock_num); 4084 } 4085 4086 STATIC cmd_result_t 4087 cmd_ptp_servo_test_mode(int unit, args_t *a) 4088 { 4089 int mode; 4090 bcm_ptp_stack_id_t stack_id = 0; 4091 int clock_num = 0; 4092 char * arg = ARG_GET(a); 4093 if (!arg) { 4094 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4095 } 4096 mode = parse_integer(arg); 4097 diag_debug_mask[unit][stack_id] &= 0x0fffffff; 4098 diag_debug_mask[unit][stack_id] |= (mode << 28); 4099 4100 return diag_set_debug(unit, stack_id, clock_num, diag_debug_mask[unit][stack_id], diag_log_mask[unit][stack_id]); 4101 } 4102 4103 STATIC cmd_result_t 4104 cmd_ptp_servo(int unit, args_t *a) 4105 { 4106 const char *arg = ARG_GET(a); 4107 4108 if (!arg) { 4109 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4110 } else if (parse_cmp("SHow", arg, 0)) { 4111 arg = ARG_GET(a); 4112 if (!arg) { /* PTP SERVO SHOW */ 4113 return cmd_ptp_servo_status_get(unit, a); 4114 } else if (parse_cmp("IPDV", arg, 0)) { /* PTP SERVO SHOW IPDV */ 4115 return cmd_ptp_servo_ipdv_perf_get(unit, a); 4116 } else if (parse_cmp("PERFormance", arg, 0)) { /* PTP SERVO SHOW PERFormance */ 4117 return cmd_ptp_servo_perf_get(unit, a); 4118 } else if (parse_cmp("PhaseHoldover", arg, 0)) { /* PTP SERVO SHOW PhaseHoldover */ 4119 return cmd_ptp_servo_phase_holdover_get(unit, a); 4120 } else if (parse_cmp("Frequency", arg, 0)) { /* PTP SERVO SHOW Frequency */ 4121 return cmd_ptp_servo_freq_corr_get(unit, a); 4122 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 4123 } else if (parse_cmp("MboxStats", arg, 0)) { /* PTP SERVO SHOW PERFormance */ 4124 _bcm_ptp_dump_mbox_tsevent_stats(); 4125 PTP_CLI_RESULT_RETURN(CMD_OK); 4126 #endif 4127 } else { 4128 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4129 } 4130 } else if (parse_cmp("CLeaR", arg, 0)) { 4131 arg = ARG_GET(a); 4132 if (!arg) { /* PTP SERVO CLEAR */ 4133 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4134 } else if (parse_cmp("PERFormance", arg, 0)) { /* PTP SERVO CLEAR PERFormance */ 4135 return cmd_ptp_servo_perf_clear(unit, a); 4136 } else { 4137 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4138 } 4139 } else if (parse_cmp("SET", arg, 0)) { 4140 arg = ARG_GET(a); 4141 if (!arg) { /* PTP SERVO SET */ 4142 cli_out(PTP_SERVO_SET_USAGE); 4143 PTP_CLI_RESULT_RETURN(CMD_FAIL); 4144 } else if (parse_cmp("Frequency", arg, 0)) { /* PTP SERVO SET FREQUENCY */ 4145 return cmd_ptp_servo_freq_corr_set(unit, a); 4146 } else if (parse_cmp("PhaseHoldover", arg, 0)) { 4147 return cmd_ptp_servo_phase_holdover_set(unit, a); 4148 } else { 4149 cli_out(PTP_SERVO_SET_USAGE); 4150 PTP_CLI_RESULT_RETURN(CMD_FAIL); 4151 } 4152 } else if (parse_cmp("CONFig", arg, 0)) { 4153 return cmd_ptp_servo_config(unit, a); 4154 } else if (parse_cmp("IPDVCONFig", arg, 0)) { 4155 return cmd_ptp_servo_ipdv_config(unit, a); 4156 } else if (parse_cmp("TESTmode", arg, 0)) { 4157 return cmd_ptp_servo_test_mode(unit, a); 4158 } 4159 4160 cli_out(PTP_SERVO_USAGE_1); 4161 cli_out(PTP_SERVO_USAGE_2); 4162 cli_out(PTP_SERVO_USAGE_3); 4163 PTP_CLI_RESULT_RETURN(CMD_FAIL); 4164 } 4165 4166 4167 /* PTP Master */ 4168 #define PTP_MASTER_USAGE_1 \ 4169 "PTP MaSTer <subcommand> [STATic[=y/n]] [Port=<port_num>] [...]\n" \ 4170 "\t PTP MaSTer ADD [IP|IPv6=<ip>] [MAC=<mac>]\n" \ 4171 "\t [logAnnounceInterval=<value>]\n" \ 4172 "\t [logSyncInterval=<value>]\n" \ 4173 "\t [logDelayreqInterval=<value>]\n" 4174 #define PTP_MASTER_USAGE_2 \ 4175 "\t [AnnounceSERVice=y/n]\n" \ 4176 "\t [SyncSERVice=y/n]\n" \ 4177 "\t [DelaySERVice=y/n]\n" \ 4178 "\t [SIGnalingDURation=<sec>]\n" \ 4179 "\t PTP MaSTer ReMove [IP|IPv6=<ip>]\n" \ 4180 "\t PTP MaSTer SHow\n" \ 4181 "\t PTP MaSTer SHow DetaiL\n" \ 4182 4183 STATIC cmd_result_t 4184 cmd_ptp_master(int unit, args_t *a) 4185 { 4186 parse_table_t pt; 4187 const char *arg = ARG_GET(a); 4188 int i; 4189 4190 bcm_ptp_stack_id_t arg_stack_id = PTP_STACK_ID_DEFAULT; 4191 int arg_clock_num = PTP_CLOCK_NUMBER_DEFAULT; 4192 int arg_port_num = PTP_CLOCK_PORT_NUMBER_DEFAULT; 4193 bcm_mac_t arg_master_mac = {0}; 4194 bcm_ip_t arg_master_ipv4 = 0; 4195 bcm_ip6_t arg_master_ipv6 = {0}; 4196 int arg_logAnnounceInterval = PTP_CLOCK_PRESETS_LOG_ANNOUNCE_INTERVAL_DEFAULT; 4197 int arg_logSyncInterval = PTP_CLOCK_PRESETS_LOG_SYNC_INTERVAL_DEFAULT; 4198 int arg_logMinDelayReqInterval = PTP_CLOCK_PRESETS_LOG_MIN_DELAY_REQ_INTERVAL_DEFAULT; 4199 int arg_announce_service = 1; 4200 int arg_sync_service = 1; 4201 int arg_delay_service = 1; 4202 int arg_durationField = -1; 4203 int arg_static_master = 0; 4204 4205 bcm_ptp_clock_port_info_t port_data; 4206 bcm_ptp_clock_unicast_master_t master; 4207 uint8 blank[16] = {0}; 4208 4209 parse_table_init(unit, &pt); 4210 parse_table_add(&pt, "Stack", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, 4211 &arg_stack_id, NULL); 4212 parse_table_add(&pt, "Clock", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, 4213 &arg_clock_num, NULL); 4214 parse_table_add(&pt, "Port", PQ_INT, (void*)PTP_CLOCK_PORT_NUMBER_DEFAULT, 4215 &arg_port_num, NULL); 4216 parse_table_add(&pt, "MAC", PQ_MAC, (void*)0, arg_master_mac, NULL); 4217 parse_table_add(&pt, "IP", PQ_IP, (void*)0, &arg_master_ipv4, NULL); 4218 parse_table_add(&pt, "IPv6", PQ_IP6, (void*)0, &arg_master_ipv6, NULL); 4219 parse_table_add(&pt, "logAnnounceInterval", PQ_INT, 4220 (void*)PTP_CLOCK_PRESETS_LOG_ANNOUNCE_INTERVAL_DEFAULT, 4221 &arg_logAnnounceInterval, NULL); 4222 parse_table_add(&pt, "logSyncInterval", PQ_INT, 4223 (void*)PTP_CLOCK_PRESETS_LOG_SYNC_INTERVAL_DEFAULT, 4224 &arg_logSyncInterval, NULL); 4225 parse_table_add(&pt, "logDelayreqInterval", PQ_INT, 4226 (void*)PTP_CLOCK_PRESETS_LOG_MIN_DELAY_REQ_INTERVAL_DEFAULT, 4227 &arg_logMinDelayReqInterval, NULL); 4228 parse_table_add(&pt, "AnnounceSERVice", PQ_BOOL, 4229 (void*)1, &arg_announce_service, NULL); 4230 parse_table_add(&pt, "SyncSERVice", PQ_BOOL, 4231 (void*)1, &arg_sync_service, NULL); 4232 parse_table_add(&pt, "DelaySERVice", PQ_BOOL, 4233 (void*)1, &arg_delay_service, NULL); 4234 parse_table_add(&pt, "SIGnalingDURation", PQ_INT, (void*)0, &arg_durationField, NULL); 4235 parse_table_add(&pt, "STATic", PQ_BOOL | PQ_NO_EQ_OPT, (void*)0, &arg_static_master, NULL); 4236 if (parse_arg_eq(a, &pt) < 0) { 4237 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 4238 } 4239 4240 /* Get local port information. */ 4241 PTP_IF_ERROR_RETURN(bcm_ptp_clock_port_info_get(unit, arg_stack_id, arg_clock_num, 4242 arg_port_num, &port_data)); 4243 4244 if (!arg) { 4245 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4246 } else if (parse_cmp("ADD", arg, 0)) { 4247 if (arg_master_ipv4 == 0 && memcmp(arg_master_ipv6, blank, sizeof(bcm_ip6_t)) == 0) { 4248 /* no IPv4 or IPv6 address was given */ 4249 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4250 } 4251 4252 /* Define master. */ 4253 sal_memset(master.address.raw_l2_header, 0, BCM_PTP_MAX_L2_HEADER_LENGTH); 4254 i = 0; 4255 memcpy(master.address.raw_l2_header, arg_master_mac, sizeof(bcm_mac_t)); 4256 i += sizeof(bcm_mac_t); 4257 memcpy(master.address.raw_l2_header + i, port_data.mac, sizeof(bcm_mac_t)); 4258 i += sizeof(bcm_mac_t); 4259 master.address.raw_l2_header[i++] = 0x81; 4260 master.address.raw_l2_header[i++] = 0x00; 4261 master.address.raw_l2_header[i++] = (uint8)(port_data.rx_packets_vlan >> 8); 4262 master.address.raw_l2_header[i++] = (uint8)(port_data.rx_packets_vlan); 4263 if (arg_master_ipv4) { 4264 /* IPv4 master. */ 4265 master.address.raw_l2_header[i++] = 0x08; 4266 master.address.raw_l2_header[i++] = 0x00; 4267 } else { 4268 /* IPv6 master. */ 4269 master.address.raw_l2_header[i++] = 0x86; 4270 master.address.raw_l2_header[i++] = 0xdd; 4271 } 4272 master.address.raw_l2_header_length = i; 4273 4274 if (arg_master_ipv4) { 4275 /* IPv4 master. */ 4276 master.address.addr_type = bcmPTPUDPIPv4; 4277 master.address.ipv4_addr = arg_master_ipv4; 4278 sal_memset(master.address.ipv6_addr, 0, sizeof(bcm_ip6_t)); 4279 } else { 4280 /* IPv6 master. */ 4281 master.address.addr_type = bcmPTPUDPIPv6; 4282 master.address.ipv4_addr = 0; 4283 sal_memcpy(master.address.ipv6_addr, arg_master_ipv6, sizeof(bcm_ip6_t)); 4284 } 4285 4286 master.log_sync_interval = arg_logSyncInterval; 4287 master.log_min_delay_request_interval = arg_logMinDelayReqInterval; 4288 4289 if (arg_static_master) { 4290 /* Static master. */ 4291 PTP_IF_ERROR_RETURN(bcm_ptp_static_unicast_master_add(unit, 4292 arg_stack_id, arg_clock_num, arg_port_num, &master)); 4293 } else { 4294 /* Signaled master. */ 4295 int logQueryRequest = 1; 4296 uint32 flags = 0; 4297 uint32 durationField; 4298 4299 if (1 == arg_announce_service) { 4300 flags |= (1u << PTP_SIGNALING_ANNOUNCE_SERVICE_BIT); 4301 } 4302 if (1 == arg_sync_service) { 4303 flags |= (1u << PTP_SIGNALING_SYNC_SERVICE_BIT); 4304 } 4305 if (1 == arg_delay_service) { 4306 flags |= (1u << PTP_SIGNALING_DELAYRESP_SERVICE_BIT); 4307 } 4308 4309 if (arg_durationField > 0) { 4310 /* 4311 * Set global REQUEST_UNICAST_TRANSMISSION TLV durationField temporarily to apply 4312 * value to new signaled master. 4313 */ 4314 PTP_IF_ERROR_RETURN(bcm_ptp_unicast_request_duration_get(unit, 4315 arg_stack_id, arg_clock_num, arg_port_num, &durationField)); 4316 PTP_IF_ERROR_RETURN(bcm_ptp_unicast_request_duration_set(unit, 4317 arg_stack_id, arg_clock_num, arg_port_num, arg_durationField)); 4318 } 4319 4320 master.log_announce_interval = arg_logAnnounceInterval; 4321 master.log_query_interval = logQueryRequest; 4322 PTP_IF_ERROR_RETURN(bcm_ptp_signaled_unicast_master_add(unit, 4323 arg_stack_id, arg_clock_num, arg_port_num, &master, flags)); 4324 4325 if ((arg_durationField > 0) && (arg_durationField != durationField)) { 4326 /* Restore default global REQUEST_UNICAST_TRANSMISSION TLV durationField. */ 4327 PTP_IF_ERROR_RETURN(bcm_ptp_unicast_request_duration_set(unit, 4328 arg_stack_id, arg_clock_num, arg_port_num, durationField)); 4329 } 4330 } 4331 4332 PTP_CLI_RESULT_RETURN(CMD_OK); 4333 4334 } else if (parse_cmp("ReMove", arg, 0)) { 4335 /* Define attributes relevant to master removal. */ 4336 if (arg_master_ipv4 == 0 && memcmp(arg_master_ipv6, blank, sizeof(bcm_ip6_t)) == 0) { 4337 /* no IPv4 or IPv6 address was given */ 4338 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4339 } 4340 4341 if (arg_master_ipv4) { 4342 /* IPv4 master. */ 4343 master.address.addr_type = bcmPTPUDPIPv4; 4344 master.address.ipv4_addr = arg_master_ipv4; 4345 sal_memset(master.address.ipv6_addr, 0, sizeof(bcm_ip6_t)); 4346 } else { 4347 /* IPv6 master. */ 4348 master.address.addr_type = bcmPTPUDPIPv6; 4349 master.address.ipv4_addr = 0; 4350 sal_memcpy(master.address.ipv6_addr, arg_master_ipv6, sizeof(bcm_ip6_t)); 4351 } 4352 4353 if (arg_static_master) { 4354 /* Static master. */ 4355 PTP_IF_ERROR_RETURN(bcm_ptp_static_unicast_master_remove(unit, 4356 arg_stack_id, arg_clock_num, arg_port_num, &master.address)); 4357 } else { 4358 /* Signaled master. */ 4359 PTP_IF_ERROR_RETURN(bcm_ptp_signaled_unicast_master_remove(unit, 4360 arg_stack_id, arg_clock_num, arg_port_num, &master.address)); 4361 } 4362 4363 PTP_CLI_RESULT_RETURN(CMD_OK); 4364 4365 } else if (parse_cmp("SHow", arg, 0)) { 4366 int num_masters = BCM_PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES; 4367 bcm_ptp_clock_peer_address_t masters[BCM_PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES]; 4368 int port = PTP_CLOCK_PORT_NUMBER_DEFAULT; 4369 arg = ARG_GET(a); 4370 4371 if (arg && parse_cmp("DetaiL", arg, 0)) { 4372 arg = ARG_GET(a); 4373 if (arg) { 4374 port = parse_integer((char*)arg); 4375 } 4376 cli_out("\n"); 4377 #ifndef __KERNEL__ 4378 BCM_IF_ERROR_RETURN(ptp_show_foreign_master_dataset(unit, cur_stack_id, cur_clock_num, port)); 4379 #endif 4380 cli_out("\n"); 4381 PTP_CLI_RESULT_RETURN(CMD_OK); 4382 } 4383 4384 PTP_IF_ERROR_RETURN(bcm_ptp_static_unicast_master_list(unit, arg_stack_id, 4385 arg_clock_num, arg_port_num, PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES, &num_masters, masters)); 4386 4387 cli_out("\n"); 4388 cli_out("All PTP Unicast Masters.\n"); 4389 cli_out("Unit: %d Stack: %d Clock: %d Port: %d\n", 4390 unit, arg_stack_id, arg_clock_num, arg_port_num); 4391 cli_out("----------------------------------------------------------------" 4392 "----------------\n"); 4393 cli_out("Entry IP\n"); 4394 cli_out("----------------------------------------------------------------" 4395 "----------------\n"); 4396 for (i = 0; i < num_masters; ++i) { 4397 cli_out("%03d ", i); 4398 switch (masters[i].addr_type) { 4399 case bcmPTPUDPIPv4: 4400 cli_out("%d.%d.%d.%d\n", 4401 (masters[i].ipv4_addr >> 24) & 0xff, 4402 (masters[i].ipv4_addr >> 16) & 0xff, 4403 (masters[i].ipv4_addr >> 8) & 0xff, 4404 (masters[i].ipv4_addr) & 0xff); 4405 break; 4406 4407 case bcmPTPUDPIPv6: 4408 cli_out("%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 4409 "%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", 4410 masters[i].ipv6_addr[0], 4411 masters[i].ipv6_addr[1], 4412 masters[i].ipv6_addr[2], 4413 masters[i].ipv6_addr[3], 4414 masters[i].ipv6_addr[4], 4415 masters[i].ipv6_addr[5], 4416 masters[i].ipv6_addr[6], 4417 masters[i].ipv6_addr[7], 4418 masters[i].ipv6_addr[8], 4419 masters[i].ipv6_addr[9], 4420 masters[i].ipv6_addr[10], 4421 masters[i].ipv6_addr[11], 4422 masters[i].ipv6_addr[12], 4423 masters[i].ipv6_addr[13], 4424 masters[i].ipv6_addr[14], 4425 masters[i].ipv6_addr[15]); 4426 break; 4427 4428 default: 4429 cli_out("Unknown\n"); 4430 } 4431 } 4432 cli_out("\n"); 4433 4434 PTP_CLI_RESULT_RETURN(CMD_OK); 4435 4436 } 4437 4438 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4439 } 4440 4441 4442 /* PTP Slave */ 4443 #define PTP_SLAVE_USAGE \ 4444 "PTP SLaVe <subcommand> [Port=<port_num>] [...]\n" \ 4445 "\t PTP SLaVe ADD [IP|IPv6=<ip>] [MAC=<mac>]\n" \ 4446 "\t [announceReceiptTimeout=<value>] [logAnnounceInterval=<value>]\n" \ 4447 "\t [logSyncInterval=<value>] [logminDelayreqInterval=<value>]\n" \ 4448 "\t PTP SLaVe ReMove [IP|IPv6=<ip>]\n" \ 4449 "\t PTP SLaVe SHow [STATic[=y/n]]\n" \ 4450 4451 STATIC cmd_result_t 4452 cmd_ptp_slave(int unit, args_t *a) 4453 { 4454 parse_table_t pt; 4455 const char *arg = ARG_GET(a); 4456 int i; 4457 4458 bcm_ptp_stack_id_t arg_stack_id = PTP_STACK_ID_DEFAULT; 4459 int arg_clock_num = PTP_CLOCK_NUMBER_DEFAULT; 4460 int arg_port_num = PTP_CLOCK_PORT_NUMBER_DEFAULT; 4461 bcm_mac_t arg_slave_mac = {0}; 4462 bcm_ip_t arg_slave_ipv4 = 0; 4463 bcm_ip6_t arg_slave_ipv6 = {0}; 4464 int arg_announceReceiptTimeout = PTP_CLOCK_PRESETS_ANNOUNCE_RECEIPT_TIMEOUT_DEFAULT; 4465 int arg_logAnnounceInterval = PTP_CLOCK_PRESETS_LOG_ANNOUNCE_INTERVAL_DEFAULT; 4466 int arg_logSyncInterval = PTP_CLOCK_PRESETS_LOG_SYNC_INTERVAL_DEFAULT; 4467 int arg_logMinDelayReqInterval = PTP_CLOCK_PRESETS_LOG_MIN_DELAY_REQ_INTERVAL_DEFAULT; 4468 int arg_static_slave = 1; 4469 4470 bcm_ptp_clock_port_info_t port_data; 4471 bcm_ptp_clock_peer_t slave; 4472 uint8 blank[16] = {0}; 4473 4474 parse_table_init(unit, &pt); 4475 parse_table_add(&pt, "Stack", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, 4476 &arg_stack_id, NULL); 4477 parse_table_add(&pt, "Clock", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, 4478 &arg_clock_num, NULL); 4479 parse_table_add(&pt, "Port", PQ_INT, (void*)PTP_CLOCK_PORT_NUMBER_DEFAULT, 4480 &arg_port_num, NULL); 4481 parse_table_add(&pt, "MAC", PQ_MAC, (void*)0, arg_slave_mac, NULL); 4482 parse_table_add(&pt, "IP", PQ_IP | PQ_DFL, (void*)0, &arg_slave_ipv4, NULL); 4483 parse_table_add(&pt, "IPv6", PQ_IP6 | PQ_DFL, (void*)0, &arg_slave_ipv6, NULL); 4484 parse_table_add(&pt, "announceReceiptTimeout", PQ_INT, 4485 (void*)PTP_CLOCK_PRESETS_ANNOUNCE_RECEIPT_TIMEOUT_DEFAULT, 4486 &arg_announceReceiptTimeout, NULL); 4487 parse_table_add(&pt, "logAnnounceInterval", PQ_INT, 4488 (void*)PTP_CLOCK_PRESETS_LOG_ANNOUNCE_INTERVAL_DEFAULT, 4489 &arg_logAnnounceInterval, NULL); 4490 parse_table_add(&pt, "logSyncInterval", PQ_INT, 4491 (void*)PTP_CLOCK_PRESETS_LOG_SYNC_INTERVAL_DEFAULT, 4492 &arg_logSyncInterval, NULL); 4493 parse_table_add(&pt, "logminDelayreqInterval", PQ_INT, 4494 (void*)PTP_CLOCK_PRESETS_LOG_MIN_DELAY_REQ_INTERVAL_DEFAULT, 4495 &arg_logMinDelayReqInterval, NULL); 4496 parse_table_add(&pt, "STATic", PQ_BOOL | PQ_NO_EQ_OPT, (void*)0, &arg_static_slave, NULL); 4497 if (parse_arg_eq(a, &pt) < 0) { 4498 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 4499 } 4500 parse_arg_eq_done(&pt); 4501 4502 /* Get local port information. */ 4503 PTP_IF_ERROR_RETURN(bcm_ptp_clock_port_info_get(unit, arg_stack_id, arg_clock_num, 4504 arg_port_num, &port_data)); 4505 4506 if (!arg) { 4507 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4508 } else if (parse_cmp("ADD", arg, 0)) { 4509 if (arg_slave_ipv4 == 0 && memcmp(arg_slave_ipv6, blank, sizeof(bcm_ip6_t)) == 0) { 4510 /* no IPv4 or IPv6 address was given */ 4511 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4512 } 4513 4514 /* Define slave. */ 4515 sal_memset(slave.clock_identity, 0, sizeof(bcm_ptp_clock_identity_t)); 4516 slave.remote_port_number = (uint16)PTP_CLOCK_PORT_NUMBER_DEFAULT; 4517 slave.local_port_number = (uint16)arg_port_num; 4518 4519 sal_memset(slave.peer_address.raw_l2_header, 0, BCM_PTP_MAX_L2_HEADER_LENGTH); 4520 i = 0; 4521 memcpy(slave.peer_address.raw_l2_header, arg_slave_mac, sizeof(bcm_mac_t)); 4522 i += sizeof(bcm_mac_t); 4523 memcpy(slave.peer_address.raw_l2_header + i, port_data.mac, sizeof(bcm_mac_t)); 4524 i += sizeof(bcm_mac_t); 4525 slave.peer_address.raw_l2_header[i++] = 0x81; 4526 slave.peer_address.raw_l2_header[i++] = 0x00; 4527 slave.peer_address.raw_l2_header[i++] = (uint8)(port_data.rx_packets_vlan >> 8); 4528 slave.peer_address.raw_l2_header[i++] = (uint8)(port_data.rx_packets_vlan); 4529 if (arg_slave_ipv4) { 4530 /* IPv4 slave. */ 4531 slave.peer_address.raw_l2_header[i++] = 0x08; 4532 slave.peer_address.raw_l2_header[i++] = 0x00; 4533 } else { 4534 /* IPv6 slave. */ 4535 slave.peer_address.raw_l2_header[i++] = 0x86; 4536 slave.peer_address.raw_l2_header[i++] = 0xdd; 4537 } 4538 slave.peer_address.raw_l2_header_length = i; 4539 4540 if (arg_slave_ipv4) { 4541 /* IPv4 slave. */ 4542 slave.peer_address.addr_type = bcmPTPUDPIPv4; 4543 slave.peer_address.ipv4_addr = arg_slave_ipv4; 4544 sal_memset(slave.peer_address.ipv6_addr, 0, sizeof(bcm_ip6_t)); 4545 } else { 4546 /* IPv6 slave. */ 4547 slave.peer_address.addr_type = bcmPTPUDPIPv6; 4548 slave.peer_address.ipv4_addr = 0; 4549 sal_memcpy(slave.peer_address.ipv6_addr, arg_slave_ipv6, sizeof(bcm_ip6_t)); 4550 } 4551 4552 slave.announce_receive_timeout = arg_announceReceiptTimeout; 4553 slave.log_announce_interval = arg_logAnnounceInterval; 4554 slave.log_sync_interval = arg_logSyncInterval; 4555 slave.log_delay_request_interval = arg_logMinDelayReqInterval; 4556 slave.log_peer_delay_request_interval = arg_logMinDelayReqInterval; 4557 4558 #if defined(PTP_KEYSTONE_STACK) 4559 slave.tx_timestamp_mech = bcmPTPToPTimestamps; 4560 #else 4561 slave.tx_timestamp_mech = port_data.rx_timestamp_mechanism; 4562 #endif 4563 slave.delay_mechanism = bcmPTPDelayMechanismEnd2End; 4564 4565 PTP_IF_ERROR_RETURN(bcm_ptp_static_unicast_slave_add(unit, arg_stack_id, 4566 arg_clock_num, arg_port_num, &slave)); 4567 4568 PTP_CLI_RESULT_RETURN(CMD_OK); 4569 4570 } else if (parse_cmp("ReMove", arg, 0)) { 4571 /* Define attributes relevant to slave removal. */ 4572 if (arg_slave_ipv4 == 0 && memcmp(arg_slave_ipv6, blank, sizeof(bcm_ip6_t)) == 0) { 4573 /* no IPv4 or IPv6 address was given */ 4574 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4575 } 4576 4577 if (arg_slave_ipv4) { 4578 /* IPv4 slave. */ 4579 slave.peer_address.addr_type = bcmPTPUDPIPv4; 4580 slave.peer_address.ipv4_addr = arg_slave_ipv4; 4581 sal_memset(slave.peer_address.ipv6_addr, 0, sizeof(bcm_ip6_t)); 4582 } else { 4583 /* IPv6 slave. */ 4584 slave.peer_address.addr_type = bcmPTPUDPIPv6; 4585 slave.peer_address.ipv4_addr = 0; 4586 sal_memcpy(slave.peer_address.ipv6_addr, arg_slave_ipv6, sizeof(bcm_ip6_t)); 4587 } 4588 4589 PTP_IF_ERROR_RETURN(bcm_ptp_static_unicast_slave_remove(unit, arg_stack_id, 4590 arg_clock_num, arg_port_num, &slave)); 4591 4592 PTP_CLI_RESULT_RETURN(CMD_OK); 4593 4594 } else if (parse_cmp("SHow", arg, 0)) { 4595 int num_slaves; 4596 bcm_ptp_clock_peer_t *slaves = sal_alloc(sizeof(bcm_ptp_clock_peer_t) * PTP_MAX_UNICAST_SLAVE_TABLE_ENTRIES, "ptpdiag"); 4597 if (!slaves) { 4598 cli_out("No memory for slave list\n"); 4599 PTP_CLI_RESULT_RETURN(CMD_FAIL); 4600 } 4601 4602 if (arg_static_slave) { 4603 int rv = bcm_ptp_static_unicast_slave_list(unit, arg_stack_id, 4604 arg_clock_num, arg_port_num, PTP_MAX_UNICAST_SLAVE_TABLE_ENTRIES, 4605 &num_slaves, slaves); 4606 if (rv < 0) { 4607 sal_free(slaves); 4608 PTP_IF_ERROR_RETURN(rv); 4609 } 4610 } else { 4611 int rv = bcm_ptp_signaled_unicast_slave_list(unit, arg_stack_id, 4612 arg_clock_num, arg_port_num, PTP_MAX_UNICAST_SLAVE_TABLE_ENTRIES, 4613 &num_slaves, slaves); 4614 if (rv < 0) { 4615 sal_free(slaves); 4616 PTP_IF_ERROR_RETURN(rv); 4617 } 4618 } 4619 4620 cli_out("\n"); 4621 if (arg_static_slave) { 4622 cli_out("PTP Static Unicast Slaves.\n"); 4623 } else { 4624 cli_out("PTP Signaled Unicast Slaves.\n"); 4625 } 4626 cli_out("Unit: %d Stack: %d Clock: %d Port: %d\n", 4627 unit, arg_stack_id, arg_clock_num, arg_port_num); 4628 cli_out("----------------------------------------------------------------" 4629 "----------------\n"); 4630 cli_out("Entry Clock Identity IP\n"); 4631 cli_out("----------------------------------------------------------------" 4632 "----------------\n"); 4633 for (i = 0; i < num_slaves; ++i) { 4634 cli_out("%03d ", i); 4635 4636 cli_out("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", 4637 slaves[i].clock_identity[0], slaves[i].clock_identity[1], slaves[i].clock_identity[2], 4638 slaves[i].clock_identity[3], slaves[i].clock_identity[4], slaves[i].clock_identity[5], 4639 slaves[i].clock_identity[6], slaves[i].clock_identity[7]); 4640 4641 switch (slaves[i].peer_address.addr_type) { 4642 case bcmPTPUDPIPv4: 4643 cli_out("%d.%d.%d.%d\n", 4644 (slaves[i].peer_address.ipv4_addr >> 24) & 0xff, 4645 (slaves[i].peer_address.ipv4_addr >> 16) & 0xff, 4646 (slaves[i].peer_address.ipv4_addr >> 8) & 0xff, 4647 (slaves[i].peer_address.ipv4_addr) & 0xff); 4648 break; 4649 4650 case bcmPTPUDPIPv6: 4651 cli_out("%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 4652 "%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", 4653 slaves[i].peer_address.ipv6_addr[0], 4654 slaves[i].peer_address.ipv6_addr[1], 4655 slaves[i].peer_address.ipv6_addr[2], 4656 slaves[i].peer_address.ipv6_addr[3], 4657 slaves[i].peer_address.ipv6_addr[4], 4658 slaves[i].peer_address.ipv6_addr[5], 4659 slaves[i].peer_address.ipv6_addr[6], 4660 slaves[i].peer_address.ipv6_addr[7], 4661 slaves[i].peer_address.ipv6_addr[8], 4662 slaves[i].peer_address.ipv6_addr[9], 4663 slaves[i].peer_address.ipv6_addr[10], 4664 slaves[i].peer_address.ipv6_addr[11], 4665 slaves[i].peer_address.ipv6_addr[12], 4666 slaves[i].peer_address.ipv6_addr[13], 4667 slaves[i].peer_address.ipv6_addr[14], 4668 slaves[i].peer_address.ipv6_addr[15]); 4669 break; 4670 4671 default: 4672 cli_out("Unknown\n"); 4673 } 4674 4675 cli_out(" logAnnounce: %+2d logSync: %+2d ", 4676 slaves[i].log_announce_interval, slaves[i].log_sync_interval); 4677 4678 switch (slaves[i].delay_mechanism) { 4679 case bcmPTPDelayMechanismEnd2End: 4680 cli_out("logDelay: %+2d (E2E)\n", slaves[i].log_delay_request_interval); 4681 break; 4682 case bcmPTPDelayMechanismPeer2Peer: 4683 cli_out("logPDelay: %+2d (P2P)\n", slaves[i].log_peer_delay_request_interval); 4684 break; 4685 default: 4686 cli_out("logDelay: ? (Unknown)\n"); 4687 } 4688 } 4689 cli_out("\n"); 4690 4691 sal_free(slaves); 4692 PTP_CLI_RESULT_RETURN(CMD_OK); 4693 4694 } else { 4695 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4696 } 4697 4698 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4699 } 4700 4701 /* PTP Peer Dataset */ 4702 #define PTP_PEER_DATASET_GET_USAGE \ 4703 "PTP PeerDataset [Port=<port_num>]\n" \ 4704 "\t Get PTP peer dataset.\n" 4705 4706 STATIC cmd_result_t 4707 cmd_ptp_peer_dataset_get(int unit, args_t *a) 4708 { 4709 int rv; 4710 4711 bcm_ptp_peer_entry_t *peers; 4712 int num_peers; 4713 int max_num_peers; 4714 4715 unsigned index; 4716 int port_num; 4717 parse_table_t pt; 4718 char uint64_decimal_string[27]; 4719 4720 max_num_peers = PTP_MAX_UNICAST_SLAVE_TABLE_ENTRIES + 4721 PTP_MAX_MULTICAST_SLAVE_STATS_ENTRIES + 4722 PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES; 4723 4724 peers = sal_alloc(sizeof(bcm_ptp_peer_entry_t) * max_num_peers, "ptpdiag_peers"); 4725 if (!peers) { 4726 cli_out("No memory for peer dataset list.\n"); 4727 PTP_CLI_RESULT_RETURN(CMD_FAIL); 4728 } 4729 4730 parse_table_init(unit, &pt); 4731 parse_table_add(&pt, "Port", PQ_INT, (void*) PTP_IEEE1588_ALL_PORTS, &port_num, NULL); 4732 if (parse_arg_eq(a, &pt) < 0) { 4733 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 4734 } 4735 parse_arg_eq_done(&pt); 4736 4737 rv = bcm_ptp_peer_dataset_get(0, PTP_STACK_ID_DEFAULT, 4738 PTP_CLOCK_NUMBER_DEFAULT, port_num, max_num_peers, peers, &num_peers); 4739 if (BCM_FAILURE(rv)) { 4740 sal_free(peers); 4741 PTP_IF_ERROR_RETURN(rv); 4742 } 4743 4744 cli_out("Number of Peers: %d\n", num_peers); 4745 for (index = 0; index < num_peers; index++) { 4746 cli_out("Peer Number: %d\n", index); 4747 cli_out("\t Port Number : %d\n", peers[index].local_port_number); 4748 cli_out("\t Clock ID : %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 4749 peers[index].clock_identity[0], 4750 peers[index].clock_identity[1], 4751 peers[index].clock_identity[2], 4752 peers[index].clock_identity[3], 4753 peers[index].clock_identity[4], 4754 peers[index].clock_identity[5], 4755 peers[index].clock_identity[6], 4756 peers[index].clock_identity[7]); 4757 4758 switch (peers[index].port_address.addr_type) { 4759 case bcmPTPUDPIPv4: 4760 cli_out("\t IPv4 : %d.%d.%d.%d\n", 4761 peers[index].port_address.address[0], peers[index].port_address.address[1], 4762 peers[index].port_address.address[2], peers[index].port_address.address[3]); 4763 break; 4764 case bcmPTPUDPIPv6: 4765 { 4766 int i; 4767 4768 cli_out("\t IPv6 : %02x%02x", peers[index].port_address.address[0], peers[index].port_address.address[1]); 4769 for (i = 2; i < 16; i += 2) { 4770 cli_out(":%02x%02x", peers[index].port_address.address[i], peers[index].port_address.address[i + 1]); 4771 } 4772 cli_out("\n"); 4773 } 4774 break; 4775 case bcmPTPIEEE8023: 4776 cli_out("\t L2: %02x:%02x:%02x:%02x:%02x:%02x\n", 4777 peers[index].port_address.address[0], peers[index].port_address.address[1], 4778 peers[index].port_address.address[2], peers[index].port_address.address[3], 4779 peers[index].port_address.address[4], peers[index].port_address.address[5]); 4780 break; 4781 default: 4782 cli_out("\t ERROR. Unexpected address type (%d)\n", peers[index].port_address.addr_type); 4783 break; 4784 } 4785 4786 format_uint64_decimal(uint64_decimal_string, peers[index].rx_announces, ','); 4787 cli_out("\t RxAnn : %s\n", uint64_decimal_string); 4788 format_uint64_decimal(uint64_decimal_string, peers[index].rx_syncs, ','); 4789 cli_out("\t RxSync : %s\n", uint64_decimal_string); 4790 format_uint64_decimal(uint64_decimal_string, peers[index].rx_followups, ','); 4791 cli_out("\t RxFlwup : %s\n", uint64_decimal_string); 4792 format_uint64_decimal(uint64_decimal_string, peers[index].rejected, ','); 4793 cli_out("\t RxRej : %s\n", uint64_decimal_string); 4794 4795 format_uint64_decimal(uint64_decimal_string, peers[index].rx_delayreqs, ','); 4796 cli_out("\t RxDlyRq : %s\n", uint64_decimal_string); 4797 format_uint64_decimal(uint64_decimal_string, peers[index].rx_delayresps, ','); 4798 cli_out("\t RxDlyRsp : %s\n", uint64_decimal_string); 4799 format_uint64_decimal(uint64_decimal_string, peers[index].rx_mgmts, ','); 4800 cli_out("\t RxMgmt : %s\n", uint64_decimal_string); 4801 format_uint64_decimal(uint64_decimal_string, peers[index].rx_signals, ','); 4802 cli_out("\t RxSig : %s\n", uint64_decimal_string); 4803 4804 format_uint64_decimal(uint64_decimal_string, peers[index].tx_announces, ','); 4805 cli_out("\t TxAnn : %s\n", uint64_decimal_string); 4806 format_uint64_decimal(uint64_decimal_string, peers[index].tx_syncs, ','); 4807 cli_out("\t TxSync : %s\n", uint64_decimal_string); 4808 format_uint64_decimal(uint64_decimal_string, peers[index].tx_followups, ','); 4809 cli_out("\t TxFlwup : %s\n", uint64_decimal_string); 4810 4811 format_uint64_decimal(uint64_decimal_string, peers[index].tx_delayreqs, ','); 4812 cli_out("\t TxDlyRq : %s\n", uint64_decimal_string); 4813 format_uint64_decimal(uint64_decimal_string, peers[index].tx_delayresps, ','); 4814 cli_out("\t TxDlyRsp : %s\n", uint64_decimal_string); 4815 format_uint64_decimal(uint64_decimal_string, peers[index].tx_mgmts, ','); 4816 cli_out("\t TxMgmt : %s\n", uint64_decimal_string); 4817 format_uint64_decimal(uint64_decimal_string, peers[index].tx_signals, ','); 4818 cli_out("\t TxSig : %s\n", uint64_decimal_string); 4819 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 4820 cli_out("\t Mod Num : %u\n", BCM_GPORT_MODPORT_MODID_GET(peers[index].phy_port)); 4821 cli_out("\t Phy Port : %u\n", BCM_GPORT_MODPORT_PORT_GET(peers[index].phy_port)); 4822 } 4823 } 4824 4825 sal_free(peers); 4826 PTP_CLI_RESULT_RETURN(CMD_OK); 4827 } 4828 4829 /* PTP Counters */ 4830 #define PTP_PACKET_COUNTERS_GET_USAGE \ 4831 "PTP CounTeRs CLeaR [Port=<port_num>] [CounterBitMaP=<counter_bitmap>]\n" \ 4832 "\t Get or Clear PTP packet counters.\n" 4833 4834 STATIC cmd_result_t 4835 cmd_ptp_packet_counters_get(int unit, args_t *a) 4836 { 4837 parse_table_t pt; 4838 bcm_ptp_stack_id_t arg_stack_id = PTP_STACK_ID_DEFAULT; 4839 int arg_clock_num = PTP_CLOCK_NUMBER_DEFAULT; 4840 int arg_port_num = BCM_PTP_IEEE1588_ALL_PORTS; 4841 int arg_ctr_bitmap = BCM_PTP_PKT_COUNTER_ALL; 4842 4843 bcm_ptp_packet_counters_t counters; 4844 int i; 4845 _bcm_ptp_clock_cache_t *clock; 4846 int num_ports, ports_per_column; 4847 const char *arg = ARG_GET(a); 4848 4849 parse_table_init(unit, &pt); 4850 parse_table_add(&pt, "Stack", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, &arg_stack_id, NULL); 4851 parse_table_add(&pt, "Clock", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, &arg_clock_num, NULL); 4852 parse_table_add(&pt, "Port", PQ_INT, (void*)-1, &arg_port_num, NULL); 4853 parse_table_add(&pt, "CounterBitMaP", PQ_INT, (void*)-1, &arg_ctr_bitmap, NULL); 4854 4855 if (parse_arg_eq(a, &pt) < 0) { 4856 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 4857 } 4858 4859 if (arg && parse_cmp("CLeaR", arg, 0)) { 4860 if ((arg_port_num == -1) && (arg_ctr_bitmap == -1)) { 4861 /* ptp ctr clear */ 4862 arg_ctr_bitmap = BCM_PTP_PKT_COUNTER_ALL; 4863 } else if ((arg_port_num != -1) && (arg_ctr_bitmap == -1)) { 4864 /* ptp ctr clear port=<> */ 4865 arg_ctr_bitmap = BCM_PTP_PKT_COUNTER_PORT_SPECIFIC; 4866 } else { 4867 /* ptp ctr clear CounterBitMaP=< > */ 4868 /* ptp ctr clear Port=< > CounterBitMaP=< > */ 4869 arg_ctr_bitmap &= BCM_PTP_PKT_COUNTER_ALL; /* Mask unused bits */ 4870 if (arg_ctr_bitmap == BCM_PTP_PKT_COUNTER_ALL || 4871 arg_ctr_bitmap <= BCM_PTP_PKT_COUNTER_COMMON) { 4872 /* To clear any/all common counters or all counters, port_num shall be 0xFFFF */ 4873 arg_port_num = PTP_IEEE1588_ALL_PORTS; 4874 } 4875 } 4876 cli_out("Unit[%d] Stack[%d] Clock[%d] Port[%d] CounterBitmap[0x%04X]\n", unit, arg_stack_id, arg_clock_num, arg_port_num, arg_ctr_bitmap); 4877 PTP_IF_ERROR_RETURN(bcm_ptp_packet_counters_clear(unit, arg_stack_id, arg_clock_num, arg_port_num, arg_ctr_bitmap)); 4878 } else { 4879 PTP_IF_ERROR_RETURN(bcm_ptp_packet_counters_get(unit, arg_stack_id, arg_clock_num, &counters)); 4880 4881 clock = &_bcm_common_ptp_unit_array[unit].stack_array[arg_stack_id].clock_array[arg_clock_num]; 4882 num_ports = clock->clock_info.num_ports; 4883 if (num_ports > 6) { 4884 ports_per_column = (num_ports + 1) / 2; /* round up */ 4885 } else { 4886 ports_per_column = num_ports; 4887 } 4888 4889 cli_out("Unit: %d Stack: %d Clock: %d\n", unit, arg_stack_id, arg_clock_num); 4890 cli_out("--------------------------------------------------------------------------------\n"); 4891 cli_out(" Tx: %-9u Rx: %-9u Disc: %-9u RCPU: %-9u\n", 4892 counters.packets_transmitted, counters.packets_received, 4893 counters.packets_discarded, counters.rcpu_encap_packets_received); 4894 cli_out("IPv4: %-9u IPv6: %-9u L2PTP: %-9u UDP: %-9u\n", 4895 counters.ipv4_packets_received, counters.ipv6_packets_received, 4896 counters.l2_ptp_packets_received, counters.udp_ptp_packets_received); 4897 cli_out("ESTx: %-9u ESRx: %-9u RxOvf: %-9u\n", 4898 counters.enduro_sync_packets_transmitted, counters.enduro_sync_packets_received, 4899 counters.rx_queue_overflows); 4900 cli_out("\n"); 4901 4902 for (i = 0; i < ports_per_column; i += 1) { 4903 cli_out(" [Port %2d] Tx: %-9u Rx: %-9u Disc: %-9u", i+1, 4904 counters.port_packets_transmitted[i], counters.port_packets_received[i], 4905 counters.port_packets_discarded[i]); 4906 if (i + ports_per_column < num_ports) { 4907 cli_out(" [Port %2d] Tx: %-9u Rx: %-9u Disc: %-9u\n", i+1+ports_per_column, 4908 counters.port_packets_transmitted[i+ports_per_column], 4909 counters.port_packets_received[i+ports_per_column], 4910 counters.port_packets_discarded[i+ports_per_column]); 4911 } else { 4912 cli_out("\n"); 4913 } 4914 } 4915 cli_out("--------------------------------------------------------------------------------\n"); 4916 cli_out("\n"); 4917 } 4918 4919 PTP_CLI_RESULT_RETURN(CMD_OK); 4920 } 4921 4922 4923 /* PTP REGISTER ARP/SIGNAL/EVENT/... */ 4924 #define PTP_REGISTER_USAGE \ 4925 "PTP REGister [Signal] [Management] [Events] [ARP]\n" \ 4926 "\t Register a diag-shell handler for callbacks on signaling messages, management messages, clock events, or ARPing.\n" 4927 4928 STATIC cmd_result_t 4929 cmd_ptp_register(int unit, args_t *a) 4930 { 4931 const char *arg = ARG_GET(a); 4932 4933 if (!arg) { 4934 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4935 } 4936 4937 while (arg) { 4938 if (parse_cmp("ARP", arg, 0)) { 4939 _bcm_ptp_arp_callback = &diag_arp_callback; 4940 PTP_IF_ERROR_RETURN(_bcm_ptp_tunnel_arp_set(unit, PTP_STACK_ID_DEFAULT, 1)); 4941 } else if (parse_cmp("Signal", arg, 0)) { 4942 PTP_IF_ERROR_RETURN(bcm_ptp_signaling_arbiter_register( 4943 unit, PTP_STACK_ID_DEFAULT, PTP_CLOCK_NUMBER_DEFAULT, 4944 diag_signaling_arbiter, 0)); 4945 } else if (parse_cmp("SignalDeny", arg, 0)) { 4946 PTP_IF_ERROR_RETURN(bcm_ptp_signaling_arbiter_register( 4947 unit, PTP_STACK_ID_DEFAULT, PTP_CLOCK_NUMBER_DEFAULT, 4948 diag_signaling_arbiter, INT_TO_PTR(ARBITER_DENY_FLAG))); 4949 } else if (parse_cmp("Management", arg, 0)) { 4950 bcm_ptp_cb_types_t cb_mask = {{0}}; 4951 SHR_BITSET(cb_mask.w, bcmPTPCallbackTypeManagement); 4952 PTP_IF_ERROR_RETURN(bcm_ptp_cb_register(unit, cb_mask, (bcm_ptp_cb)diag_management_callback, 0)); 4953 } else if (parse_cmp("Events", arg, 0)) { 4954 bcm_ptp_cb_types_t cb_mask = {{0}}; 4955 SHR_BITSET(cb_mask.w, bcmPTPCallbackTypeEvent); 4956 PTP_IF_ERROR_RETURN(bcm_ptp_cb_register(unit, cb_mask, (bcm_ptp_cb)diag_event_callback, 0)); 4957 } else { 4958 PTP_CLI_RESULT_RETURN(CMD_USAGE); 4959 } 4960 arg = ARG_GET(a); 4961 } 4962 4963 PTP_CLI_RESULT_RETURN(CMD_OK); 4964 } 4965 4966 4967 /* PTP TELecom */ 4968 /* We divide the string because pedantic compiler doesn't allow strings longer then 509 characters */ 4969 #define PTP_TELECOM_USAGE_1 \ 4970 "PTP TELecom <subcommand> [...]\n" \ 4971 "\t PTP TELecom CLOCK CREATE [ID=<xx:xx:xx:xx:xx:xx:xx:xx>]\n" \ 4972 "\t [QL=<ITU-T G.781 QL>] [DOMain=<value>]\n" \ 4973 "\t [SlaveOnly=y/n] [OneWay=y/n]\n" \ 4974 "\t PTP TELecom PORT CONFig [IP=<ip>] [MAC=<mac>]\n" \ 4975 "\t [VLAN=<value>] [PRIO=<value>]\n" \ 4976 "\t [TimeStamp=<|ToP|RCPU|PHY|Unimac32|Unimac48|>]\n" \ 4977 "\t PTP TELecom SLaVe CONFig [ENable=<|DISable|OPTionI|OPTionII|OPTionIII|>]\n" \ 4978 "\t " 4979 #define PTP_TELECOM_USAGE_2 \ 4980 "[SyncReceiptTimeout=<msec>]\n" \ 4981 "\t [DelayReceiptTimeout=<msec>]\n" \ 4982 "\t [VARianceTHRESHold=<nsec_sq>]\n" \ 4983 "\t PTP TELecom SLaVe SHow\n" \ 4984 "\t PTP TELecom MaSTer CONFig [IP=<ip>] [PRIOrity=<value>]\n" \ 4985 "\t [OVeRride=y/n] [LoCKout=y/n]\n" \ 4986 "\t [NONREVersion=y/n]\n" \ 4987 "\t [WAIT_to_restore=<sec>]\n" \ 4988 "\t PTP TELecom MaSTer SHow [DeTaiLs=y/n]\n" \ 4989 "\t PTP TELecom MaSTer BeST [DeTaiLs=y/n]\n" \ 4990 "\t PTP TELecom OPTions [VERBose=y/n]\n" 4991 4992 STATIC cmd_result_t 4993 cmd_ptp_telecom(int unit, args_t *a) 4994 { 4995 parse_table_t pt; 4996 const char *arg = ARG_GET(a); 4997 int i; 4998 4999 bcm_ptp_stack_id_t arg_stack_id = PTP_STACK_ID_DEFAULT; 5000 int arg_clock_num = PTP_CLOCK_NUMBER_DEFAULT; 5001 5002 char *arg_clockIdentity; 5003 char *id_token; 5004 char *id_rem; 5005 5006 char *arg_QL; 5007 int arg_domainNumber = PTP_CLOCK_PRESETS_TELECOM_DOMAIN_NUMBER_DEFAULT; 5008 int arg_slaveOnly = 0; 5009 int arg_oneWay = 0; 5010 5011 bcm_ip_t arg_port_ip = (192 << 24) + (168 << 16) + 31; 5012 bcm_mac_t arg_port_mac = {0}; 5013 int arg_port_vlan = 1; 5014 int arg_port_prio = 0; 5015 char *arg_timestamp_mechanism = 0; 5016 5017 char *arg_telecom_enable; 5018 int arg_syncReceiptTimeout = PTP_TELECOM_SYNC_RECEIPT_TIMEOUT_MSEC_DEFAULT; 5019 int arg_delayReceiptTimeout = PTP_TELECOM_DELAYRESP_RECEIPT_TIMEOUT_MSEC_DEFAULT; 5020 uint64 arg_varianceThreshold; 5021 5022 bcm_ip_t arg_pktmaster_ipv4 = 0; 5023 int arg_pktmaster_priority = 0; 5024 int arg_pktmaster_override = 0; 5025 int arg_pktmaster_lockout = 0; 5026 int arg_pktmaster_non_reversion = PTP_TELECOM_NON_REVERSION_MODE_DEFAULT; 5027 uint64 arg_pktmaster_wait_sec; 5028 5029 int arg_details = 0; 5030 int arg_verbose = 1; 5031 5032 bcm_ptp_telecom_g8265_network_option_t network_option; 5033 bcm_ptp_telecom_g8265_quality_level_t QL; 5034 bcm_ptp_clock_port_address_t address; 5035 5036 uint32 slaveOnly; 5037 uint32 receiptTimeout; 5038 bcm_ptp_telecom_g8265_pktstats_t thresholds; 5039 5040 int num_masters; 5041 int best_master; 5042 bcm_ptp_telecom_g8265_pktmaster_t pktmaster[PTP_TELECOM_MAX_NUMBER_PKTMASTERS]; 5043 char *tokstr =NULL; 5044 char uint64_decimal_string[27]; 5045 5046 COMPILER_64_SET(arg_pktmaster_wait_sec, 0, PTP_TELECOM_WAIT_TO_RESTORE_SEC_DEFAULT); 5047 5048 if (!arg) { 5049 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5050 } else if (parse_cmp("CLOCK", arg, 0)) { 5051 bcm_ptp_clock_info_t clockInfo; 5052 clockInfo.flags = (1u << PTP_CLOCK_FLAGS_TELECOM_PROFILE_BIT); 5053 clockInfo.clock_num = PTP_CLOCK_NUMBER_DEFAULT; 5054 clockInfo.clock_identity[0] = 0x00; 5055 clockInfo.clock_identity[1] = 0x00; 5056 clockInfo.clock_identity[2] = 0x00; 5057 clockInfo.clock_identity[3] = 0xff; 5058 clockInfo.clock_identity[4] = 0xfe; 5059 clockInfo.clock_identity[5] = 0x00; 5060 clockInfo.clock_identity[6] = 0x00; 5061 clockInfo.clock_identity[7] = 0x00; 5062 clockInfo.type = bcmPTPClockTypeOrdinary; 5063 clockInfo.num_ports = 1; 5064 clockInfo.clock_class = 108; /* QL-PROV, ITU-T G.781 network option II clockClass. */ 5065 clockInfo.domain_number = PTP_CLOCK_PRESETS_TELECOM_DOMAIN_NUMBER_DEFAULT; 5066 clockInfo.scaled_log_variance = 1; 5067 clockInfo.priority1 = PTP_CLOCK_PRESETS_PRIORITY1_DEFAULT; 5068 clockInfo.priority2 = PTP_CLOCK_PRESETS_PRIORITY2_DEFAULT; 5069 clockInfo.slaveonly = arg_slaveOnly; 5070 clockInfo.twostep = 1; 5071 clockInfo.tc_primary_domain = PTP_CLOCK_PRESETS_TELECOM_DOMAIN_NUMBER_DEFAULT; 5072 clockInfo.tc_delay_mechanism = bcmPTPDelayMechanismEnd2End; 5073 clockInfo.announce_receipt_timeout_minimum = 5074 PTP_CLOCK_PRESETS_ANNOUNCE_RECEIPT_TIMEOUT_MINIMUM; 5075 clockInfo.announce_receipt_timeout_default = 5076 PTP_CLOCK_PRESETS_ANNOUNCE_RECEIPT_TIMEOUT_DEFAULT; 5077 clockInfo.announce_receipt_timeout_maximum = 5078 PTP_CLOCK_PRESETS_ANNOUNCE_RECEIPT_TIMEOUT_MAXIMUM; 5079 clockInfo.log_announce_interval_minimum = 5080 PTP_CLOCK_PRESETS_TELECOM_LOG_ANNOUNCE_INTERVAL_MINIMUM; 5081 clockInfo.log_announce_interval_default = 5082 PTP_CLOCK_PRESETS_TELECOM_LOG_ANNOUNCE_INTERVAL_DEFAULT; 5083 clockInfo.log_announce_interval_maximum = 5084 PTP_CLOCK_PRESETS_TELECOM_LOG_ANNOUNCE_INTERVAL_MAXIMUM; 5085 clockInfo.log_sync_interval_minimum = 5086 PTP_CLOCK_PRESETS_TELECOM_LOG_SYNC_INTERVAL_MINIMUM; 5087 clockInfo.log_sync_interval_default = 5088 PTP_CLOCK_PRESETS_TELECOM_LOG_SYNC_INTERVAL_DEFAULT; 5089 clockInfo.log_sync_interval_maximum = 5090 PTP_CLOCK_PRESETS_TELECOM_LOG_SYNC_INTERVAL_MAXIMUM; 5091 clockInfo.log_min_delay_req_interval_minimum = 5092 PTP_CLOCK_PRESETS_TELECOM_LOG_MIN_DELAY_REQ_INTERVAL_MINIMUM; 5093 clockInfo.log_min_delay_req_interval_default = 5094 PTP_CLOCK_PRESETS_TELECOM_LOG_MIN_DELAY_REQ_INTERVAL_DEFAULT; 5095 clockInfo.log_min_delay_req_interval_maximum = 5096 PTP_CLOCK_PRESETS_TELECOM_LOG_MIN_DELAY_REQ_INTERVAL_MAXIMUM; 5097 clockInfo.domain_number_minimum = 5098 PTP_CLOCK_PRESETS_TELECOM_DOMAIN_NUMBER_MINIMUM; 5099 clockInfo.domain_number_default = 5100 PTP_CLOCK_PRESETS_TELECOM_DOMAIN_NUMBER_DEFAULT; 5101 clockInfo.domain_number_maximum = 5102 PTP_CLOCK_PRESETS_TELECOM_DOMAIN_NUMBER_MAXIMUM; 5103 clockInfo.priority1_minimum = PTP_CLOCK_PRESETS_PRIORITY1_MINIMUM; 5104 clockInfo.priority1_default = PTP_CLOCK_PRESETS_PRIORITY1_DEFAULT; 5105 clockInfo.priority1_maximum = PTP_CLOCK_PRESETS_PRIORITY1_MAXIMUM; 5106 clockInfo.priority2_minimum = PTP_CLOCK_PRESETS_PRIORITY2_MINIMUM; 5107 clockInfo.priority2_default = PTP_CLOCK_PRESETS_PRIORITY2_DEFAULT; 5108 clockInfo.priority2_maximum = PTP_CLOCK_PRESETS_PRIORITY2_MAXIMUM; 5109 clockInfo.number_virtual_interfaces = 0; 5110 5111 arg = ARG_GET(a); 5112 if (!arg) { 5113 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5114 } else if (parse_cmp("CREATE", arg, 0)) { 5115 parse_table_init(unit, &pt); 5116 parse_table_add(&pt, "Stack", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, 5117 &arg_stack_id, NULL); 5118 parse_table_add(&pt, "Clock", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, 5119 &arg_clock_num, NULL); 5120 parse_table_add(&pt, "ID", PQ_STRING, (void*)"00:00:00:ff:fe:00:00:00", 5121 &arg_clockIdentity, NULL); 5122 parse_table_add(&pt, "QL", PQ_STRING, (void*)"QL-PROV", 5123 &arg_QL, NULL); 5124 parse_table_add(&pt, "DOMain", PQ_INT, (void*)PTP_CLOCK_PRESETS_TELECOM_DOMAIN_NUMBER_DEFAULT, 5125 &arg_domainNumber, NULL); 5126 parse_table_add(&pt, "SlaveOnly", PQ_BOOL, (void*)0, 5127 &arg_slaveOnly, NULL); 5128 parse_table_add(&pt, "OneWay", PQ_BOOL, (void*)0, 5129 &arg_oneWay, NULL); 5130 if (parse_arg_eq(a, &pt) < 0) { 5131 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 5132 } 5133 5134 if (1 == arg_slaveOnly) { 5135 QL = bcm_ptp_telecom_g8265_ql_na_slv; 5136 } else if (arg_QL) { 5137 if (parse_cmp("QL-PRC", arg_QL, 0)) { 5138 QL = bcm_ptp_telecom_g8265_ql_I_prc; 5139 } else if (parse_cmp("QL-SSU-A", arg_QL, 0)) { 5140 QL = bcm_ptp_telecom_g8265_ql_I_ssua; 5141 } else if (parse_cmp("QL-SSU-B", arg_QL, 0)) { 5142 QL = bcm_ptp_telecom_g8265_ql_I_ssub; 5143 } else if (parse_cmp("QL-SEC", arg_QL, 0)) { 5144 5145 QL = bcm_ptp_telecom_g8265_ql_I_sec; 5146 /* 5147 switch (network_option) { 5148 case bcm_ptp_telecom_g8265_network_option_I: 5149 QL = bcm_ptp_telecom_g8265_ql_I_sec; 5150 break; 5151 case bcm_ptp_telecom_g8265_network_option_III: 5152 QL = bcm_ptp_telecom_g8265_ql_III_sec; 5153 break; 5154 default: 5155 QL = bcm_ptp_telecom_g8265_ql_invalid; 5156 } 5157 */ 5158 } else if (parse_cmp("QL-DNU", arg_QL, 0)) { 5159 QL = bcm_ptp_telecom_g8265_ql_I_dnu; 5160 } else if (parse_cmp("QL-PRS", arg_QL, 0)) { 5161 QL = bcm_ptp_telecom_g8265_ql_II_prs; 5162 } else if (parse_cmp("QL-STU", arg_QL, 0)) { 5163 QL = bcm_ptp_telecom_g8265_ql_II_stu; 5164 } else if (parse_cmp("QL-ST2", arg_QL, 0)) { 5165 QL = bcm_ptp_telecom_g8265_ql_II_st2; 5166 } else if (parse_cmp("QL-TNC", arg_QL, 0)) { 5167 QL = bcm_ptp_telecom_g8265_ql_II_tnc; 5168 } else if (parse_cmp("QL-ST3E", arg_QL, 0)) { 5169 QL = bcm_ptp_telecom_g8265_ql_II_st3e; 5170 } else if (parse_cmp("QL-ST3", arg_QL, 0)) { 5171 QL = bcm_ptp_telecom_g8265_ql_II_st3; 5172 } else if (parse_cmp("QL-SMC", arg_QL, 0)) { 5173 QL = bcm_ptp_telecom_g8265_ql_II_smc; 5174 } else if (parse_cmp("QL-PROV", arg_QL, 0)) { 5175 QL = bcm_ptp_telecom_g8265_ql_II_prov; 5176 } else if (parse_cmp("QL-DUS", arg_QL, 0)) { 5177 QL = bcm_ptp_telecom_g8265_ql_II_dus; 5178 } else if (parse_cmp("QL-UNK", arg_QL, 0)) { 5179 QL = bcm_ptp_telecom_g8265_ql_III_unk; 5180 } else { 5181 QL = bcm_ptp_telecom_g8265_ql_invalid; 5182 } 5183 } else { 5184 QL = bcm_ptp_telecom_g8265_ql_invalid; 5185 } 5186 5187 /* 5188 * Create telecom-compliant PTP clock (OC). 5189 * Set configurable members of clock info. 5190 */ 5191 if (1 == arg_oneWay) { 5192 clockInfo.flags |= (1u << PTP_CLOCK_FLAGS_ONEWAY_BIT); 5193 } 5194 5195 clockInfo.clock_num = arg_clock_num; 5196 5197 id_token = sal_strtok_r(arg_clockIdentity, ":", &tokstr); 5198 i = 0; 5199 while ((id_token != NULL) && (i < BCM_PTP_CLOCK_EUID_IEEE1588_SIZE)) { 5200 clockInfo.clock_identity[i++] = strtol(id_token, &id_rem, 16); 5201 id_token = sal_strtok_r(NULL, ":", &tokstr); 5202 } 5203 if (i != BCM_PTP_CLOCK_EUID_IEEE1588_SIZE) { 5204 cli_out("Error: Invalid clockIdentity format\n"); 5205 cli_out("\n"); 5206 parse_arg_eq_done(&pt); 5207 PTP_CLI_RESULT_RETURN(CMD_FAIL); 5208 } 5209 parse_arg_eq_done(&pt); 5210 5211 PTP_IF_ERROR_RETURN(_bcm_ptp_telecom_g8265_map_QL_clockClass(QL, &clockInfo.clock_class)); 5212 clockInfo.domain_number = arg_domainNumber; 5213 5214 clockInfo.slaveonly = arg_slaveOnly; 5215 5216 PTP_IF_ERROR_RETURN(bcm_ptp_clock_create(unit, arg_stack_id, &clockInfo)); 5217 5218 PTP_CLI_RESULT_RETURN(CMD_OK); 5219 5220 } else { 5221 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5222 } 5223 5224 } else if (parse_cmp("PORT", arg, 0)) { 5225 5226 bcm_ptp_clock_port_info_t portInfo; 5227 5228 portInfo.port_address.addr_type = bcmPTPUDPIPv4; 5229 sal_memset(portInfo.port_address.address, 0, sizeof(portInfo.port_address.address)); 5230 sal_memset(portInfo.mac, 0, sizeof(portInfo.mac)); 5231 portInfo.multicast_l2_size = 0; 5232 sal_memset(portInfo.multicast_l2, 0, sizeof(portInfo.multicast_l2)); 5233 portInfo.multicast_pdelay_l2_size = 0; 5234 sal_memset(portInfo.multicast_pdelay_l2, 0, sizeof(portInfo.multicast_pdelay_l2)); 5235 portInfo.multicast_tx_enable = 0; 5236 portInfo.port_type = bcmPTPPortTypeStandard; 5237 portInfo.announce_receipt_timeout = 5238 PTP_CLOCK_PRESETS_ANNOUNCE_RECEIPT_TIMEOUT_DEFAULT; 5239 portInfo.log_announce_interval = 5240 PTP_CLOCK_PRESETS_TELECOM_LOG_ANNOUNCE_INTERVAL_DEFAULT; 5241 portInfo.log_sync_interval = 5242 PTP_CLOCK_PRESETS_TELECOM_LOG_SYNC_INTERVAL_DEFAULT; 5243 portInfo.log_min_delay_req_interval = 5244 PTP_CLOCK_PRESETS_TELECOM_LOG_MIN_DELAY_REQ_INTERVAL_DEFAULT; 5245 portInfo.delay_mechanism = bcmPTPDelayMechanismEnd2End; 5246 portInfo.rx_timestamp_mechanism = bcmPTPMac32CorrectionTimestamps; 5247 portInfo.rx_packets_vlan = (arg_port_vlan + (arg_port_prio << 13)); 5248 portInfo.rx_packets_port_mask_high32 = 0; 5249 portInfo.rx_packets_port_mask_low32 = 0; 5250 portInfo.rx_packets_criteria_mask = 0; 5251 5252 arg = ARG_GET(a); 5253 if (!arg) { 5254 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5255 } else if (parse_cmp("CONFig", arg, 0)) { 5256 parse_table_init(unit, &pt); 5257 parse_table_add(&pt, "Stack", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, 5258 &arg_stack_id, NULL); 5259 parse_table_add(&pt, "Clock", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, 5260 &arg_clock_num, NULL); 5261 parse_table_add(&pt, "IP", PQ_IP, (void*)(size_t)arg_port_ip, 5262 &arg_port_ip, NULL); 5263 parse_table_add(&pt, "MAC", PQ_MAC, (void*)arg_port_mac, 5264 &arg_port_mac, NULL); 5265 parse_table_add(&pt, "VLAN", PQ_INT, (void*)1, 5266 &arg_port_vlan, NULL); 5267 parse_table_add(&pt, "PRIO", PQ_INT, (void*)0, 5268 &arg_port_prio, NULL); 5269 parse_table_add(&pt, "TimeStamp", PQ_STRING, (void*)"", 5270 &arg_timestamp_mechanism, NULL); 5271 if (parse_arg_eq(a, &pt) < 0) { 5272 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 5273 } 5274 5275 /* Configure PTP port. */ 5276 portInfo.port_address.address[0] = (uint8)(arg_port_ip >> 24); 5277 portInfo.port_address.address[1] = (uint8)(arg_port_ip >> 16); 5278 portInfo.port_address.address[2] = (uint8)(arg_port_ip >> 8); 5279 portInfo.port_address.address[3] = (uint8)(arg_port_ip); 5280 5281 sal_memcpy(portInfo.mac, arg_port_mac, sizeof(bcm_mac_t)); 5282 portInfo.rx_packets_vlan = (arg_port_vlan + (arg_port_prio << 13)); 5283 5284 #if defined(PTP_KEYSTONE_STACK) 5285 portInfo.rx_timestamp_mechanism = bcmPTPToPTimestamps; 5286 #else 5287 portInfo.rx_timestamp_mechanism = bcmPTPMac32CorrectionTimestamps; 5288 #endif 5289 5290 if (arg_timestamp_mechanism) { 5291 if (parse_cmp("ToP", arg_timestamp_mechanism, 0)) { 5292 portInfo.rx_timestamp_mechanism = bcmPTPToPTimestamps; 5293 } else if (parse_cmp("RCPU", arg_timestamp_mechanism, 0)) { 5294 portInfo.rx_timestamp_mechanism = bcmPTPRCPUTimestamps; 5295 } else if (parse_cmp("PHY", arg_timestamp_mechanism, 0)) { 5296 portInfo.rx_timestamp_mechanism = bcmPTPPhyCorrectionTimestamps; 5297 } else if (parse_cmp("Unimac32", arg_timestamp_mechanism, 0)) { 5298 portInfo.rx_timestamp_mechanism = bcmPTPMac32CorrectionTimestamps; 5299 } else if (parse_cmp("Unimac48", arg_timestamp_mechanism, 0)) { 5300 portInfo.rx_timestamp_mechanism = bcmPTPMac48CorrectionTimestamps; 5301 } 5302 5303 } 5304 parse_arg_eq_done(&pt); 5305 5306 PTP_IF_ERROR_RETURN(bcm_ptp_clock_port_configure(unit, arg_stack_id, 5307 arg_clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT, &portInfo)); 5308 5309 PTP_CLI_RESULT_RETURN(CMD_OK); 5310 5311 } else { 5312 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5313 } 5314 5315 } else if (parse_cmp("SLaVe", arg, 0)) { 5316 /* Pre-check(s). */ 5317 PTP_IF_ERROR_RETURN(bcm_ptp_clock_slaveonly_get(unit, PTP_STACK_ID_DEFAULT, 5318 PTP_CLOCK_NUMBER_DEFAULT, &slaveOnly)); 5319 if (0 == slaveOnly) { 5320 cli_out("PTP TELECOM SLAVE commands applicable to slaveOnly clock.\n"); 5321 cli_out("\n"); 5322 PTP_IF_ERROR_RETURN(BCM_E_UNAVAIL); 5323 } 5324 5325 arg = ARG_GET(a); 5326 if (!arg) { 5327 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5328 } else if (parse_cmp("CONFig", arg, 0)) { 5329 /* Defaults. */ 5330 COMPILER_64_SET(arg_varianceThreshold, 0, PTP_TELECOM_PDV_SCALED_ALLAN_VARIANCE_THRESHOLD_NSECSQ_DEFAULT); 5331 5332 parse_table_init(unit, &pt); 5333 parse_table_add(&pt, "Stack", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, 5334 &arg_stack_id, NULL); 5335 parse_table_add(&pt, "Clock", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, 5336 &arg_clock_num, NULL); 5337 parse_table_add(&pt, "ENable", PQ_STRING, (void*)"DISable", 5338 &arg_telecom_enable, NULL); 5339 parse_table_add(&pt, "SyncReceiptTimeout", PQ_INT, 5340 (void*)PTP_TELECOM_SYNC_RECEIPT_TIMEOUT_MSEC_DEFAULT, 5341 &arg_syncReceiptTimeout, NULL); 5342 parse_table_add(&pt, "DelayReceiptTimeout", PQ_INT, 5343 (void*)PTP_TELECOM_DELAYRESP_RECEIPT_TIMEOUT_MSEC_DEFAULT, 5344 &arg_delayReceiptTimeout, NULL); 5345 parse_table_add(&pt, "VARianceTHRESHold", PQ_DFL|PQ_INT64, 5346 (void*)PTP_TELECOM_PDV_SCALED_ALLAN_VARIANCE_THRESHOLD_NSECSQ_DEFAULT, 5347 &arg_varianceThreshold, NULL); 5348 if (parse_arg_eq(a, &pt) < 0) { 5349 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 5350 } 5351 5352 if (parse_cmp("DISable", arg_telecom_enable, 0)) { 5353 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_network_option_set(unit, 5354 arg_stack_id, arg_clock_num, bcm_ptp_telecom_g8265_network_option_disable)); 5355 PTP_CLI_RESULT_RETURN(CMD_OK); 5356 } else if (parse_cmp("OPTionI", arg_telecom_enable, 0)) { 5357 network_option = bcm_ptp_telecom_g8265_network_option_I; 5358 } else if (parse_cmp("OPTionII", arg_telecom_enable, 0)) { 5359 network_option = bcm_ptp_telecom_g8265_network_option_II; 5360 } else if (parse_cmp("OPTionIII", arg_telecom_enable, 0)) { 5361 network_option = bcm_ptp_telecom_g8265_network_option_III; 5362 } else { 5363 parse_arg_eq_done(&pt); 5364 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5365 } 5366 parse_arg_eq_done(&pt); 5367 5368 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_network_option_set(unit, 5369 arg_stack_id, arg_clock_num, network_option)); 5370 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_quality_level_set(unit, 5371 arg_stack_id, arg_clock_num, bcm_ptp_telecom_g8265_ql_na_slv)); 5372 5373 /* Packet slave configuration settings. */ 5374 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_receipt_timeout_set(unit, 5375 arg_stack_id, arg_clock_num, bcmPTP_MESSAGE_TYPE_SYNC, (uint32)arg_syncReceiptTimeout)); 5376 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_receipt_timeout_set(unit, 5377 arg_stack_id, arg_clock_num, bcmPTP_MESSAGE_TYPE_DELAY_RESP, (uint32)arg_delayReceiptTimeout)); 5378 5379 COMPILER_64_SET(thresholds.pdv_scaled_allan_var, 5380 COMPILER_64_HI(arg_varianceThreshold), 5381 COMPILER_64_LO(arg_varianceThreshold)); 5382 5383 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_pktstats_thresholds_set(unit, 5384 arg_stack_id, arg_clock_num, thresholds)); 5385 5386 PTP_CLI_RESULT_RETURN(CMD_OK); 5387 5388 } else if (parse_cmp("SHow", arg, 0)) { 5389 cli_out("\n"); 5390 cli_out("Telecom Profile Slave Configuration (Control Parameters).\n"); 5391 cli_out("Unit: %d Stack: %d Clock: %d\n", 5392 unit, arg_stack_id, arg_clock_num); 5393 cli_out("-----------------------------------------------------------" 5394 "---------------------\n"); 5395 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_network_option_get(unit, arg_stack_id, 5396 arg_clock_num, &network_option)); 5397 switch (network_option) { 5398 case (bcm_ptp_telecom_g8265_network_option_I): 5399 cli_out("ITU-T G.781 network option : Option I\n"); 5400 break; 5401 case (bcm_ptp_telecom_g8265_network_option_II): 5402 cli_out("ITU-T G.781 network option : Option II\n"); 5403 break; 5404 case (bcm_ptp_telecom_g8265_network_option_III): 5405 cli_out("ITU-T G.781 network option : Option III\n"); 5406 break; 5407 default: 5408 cli_out("ITU-T G.781 network option : <Invalid>\n"); 5409 } 5410 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_receipt_timeout_get(unit, arg_stack_id, 5411 arg_clock_num, bcmPTP_MESSAGE_TYPE_SYNC, &receiptTimeout)); 5412 cli_out("Sync Timeout : %u (msec)\n", receiptTimeout); 5413 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_receipt_timeout_get(unit, arg_stack_id, 5414 arg_clock_num, bcmPTP_MESSAGE_TYPE_DELAY_RESP, &receiptTimeout)); 5415 cli_out("Delay_Resp Timeout : %u (msec)\n", receiptTimeout); 5416 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_pktstats_thresholds_get(unit, arg_stack_id, 5417 arg_clock_num, &thresholds)); 5418 format_uint64_decimal(uint64_decimal_string, thresholds.pdv_scaled_allan_var, ','); 5419 cli_out("Scaled AVAR Threshold : %s (nsec-sq)\n", uint64_decimal_string); 5420 5421 PTP_CLI_RESULT_RETURN(CMD_OK); 5422 5423 } else { 5424 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5425 } 5426 5427 } else if (parse_cmp("MaSTer", arg, 0)) { 5428 /* Pre-check(s). */ 5429 PTP_IF_ERROR_RETURN(bcm_ptp_clock_slaveonly_get(unit, PTP_STACK_ID_DEFAULT, 5430 PTP_CLOCK_NUMBER_DEFAULT, &slaveOnly)); 5431 if (0 == slaveOnly) { 5432 cli_out("PTP TELECOM MASTER commands applicable to slaveOnly clock.\n"); 5433 cli_out("\n"); 5434 PTP_IF_ERROR_RETURN(BCM_E_UNAVAIL); 5435 } 5436 5437 arg = ARG_GET(a); 5438 if (!arg) { 5439 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5440 } else if (parse_cmp("CONFig", arg, 0)) { 5441 parse_table_init(unit, &pt); 5442 parse_table_add(&pt, "Stack", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, 5443 &arg_stack_id, NULL); 5444 parse_table_add(&pt, "Clock", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, 5445 &arg_clock_num, NULL); 5446 parse_table_add(&pt, "IP", PQ_IP | PQ_DFL, (void*)0, &arg_pktmaster_ipv4, NULL); 5447 parse_table_add(&pt, "PRIOrity", PQ_INT, (void*)0, &arg_pktmaster_priority, NULL); 5448 parse_table_add(&pt, "OVeRride", PQ_BOOL, (void*)0, &arg_pktmaster_override, NULL); 5449 parse_table_add(&pt, "LoCKout", PQ_BOOL, (void*)0, &arg_pktmaster_lockout, NULL); 5450 parse_table_add(&pt, "NONREVersion", PQ_BOOL, 5451 (void*)PTP_TELECOM_NON_REVERSION_MODE_DEFAULT, 5452 &arg_pktmaster_non_reversion, NULL); 5453 parse_table_add(&pt, "WAIT_to_restore", PQ_DFL|PQ_INT64, 5454 (void*)PTP_TELECOM_WAIT_TO_RESTORE_SEC_DEFAULT, 5455 &arg_pktmaster_wait_sec, NULL); 5456 if (parse_arg_eq(a, &pt) < 0) { 5457 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 5458 } 5459 parse_arg_eq_done(&pt); 5460 5461 address.addr_type = bcmPTPUDPIPv4; 5462 sal_memset(address.address, 0, BCM_PTP_MAX_NETW_ADDR_SIZE); 5463 address.address[0] = ((arg_pktmaster_ipv4 >> 24) & 0xff); 5464 address.address[1] = ((arg_pktmaster_ipv4 >> 16) & 0xff); 5465 address.address[2] = ((arg_pktmaster_ipv4 >> 8) & 0xff); 5466 address.address[3] = (arg_pktmaster_ipv4 & 0xff); 5467 5468 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_packet_master_priority_set( 5469 unit, arg_stack_id, arg_clock_num, (uint16)arg_pktmaster_priority, 5470 &address)); 5471 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_packet_master_priority_override( 5472 unit, arg_stack_id, arg_clock_num, (uint8)arg_pktmaster_override, 5473 &address)); 5474 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_packet_master_lockout_set( 5475 unit, arg_stack_id, arg_clock_num, (uint8)arg_pktmaster_lockout, 5476 &address)); 5477 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_packet_master_non_reversion_set( 5478 unit, arg_stack_id, arg_clock_num, (uint8)arg_pktmaster_non_reversion, 5479 &address)); 5480 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_packet_master_wait_duration_set( 5481 unit, arg_stack_id, arg_clock_num, arg_pktmaster_wait_sec, 5482 &address)); 5483 5484 PTP_CLI_RESULT_RETURN(CMD_OK); 5485 5486 } else if (parse_cmp("SHow", arg, 0)) { 5487 parse_table_init(unit, &pt); 5488 parse_table_add(&pt, "Stack", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, 5489 &arg_stack_id, NULL); 5490 parse_table_add(&pt, "Clock", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, 5491 &arg_clock_num, NULL); 5492 parse_table_add(&pt, "DeTaiLs", PQ_BOOL, (void*)0, &arg_details, NULL); 5493 if (parse_arg_eq(a, &pt) < 0) { 5494 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 5495 } 5496 parse_arg_eq_done(&pt); 5497 5498 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_packet_master_list(unit, 5499 arg_stack_id, arg_clock_num, PTP_TELECOM_MAX_NUMBER_PKTMASTERS, 5500 &num_masters, &best_master, pktmaster)); 5501 5502 cli_out("\n"); 5503 cli_out("Telecom Profile Packet Masters.\n"); 5504 cli_out("Unit: %d Stack: %d Clock: %d\n", 5505 unit, arg_stack_id, arg_clock_num); 5506 cli_out("-----------------------------------------------------------" 5507 "---------------------\n"); 5508 cli_out("Number Masters : %u\n", num_masters); 5509 if (num_masters) { 5510 cli_out("Best Master : %u\n", best_master); 5511 } else { 5512 cli_out("Best Master :\n"); 5513 } 5514 for (i = 0; i < num_masters; ++i) { 5515 cli_out("------------------------------------- [%02d] ----------" 5516 "---------------------------\n", i); 5517 diag_telecom_pktmaster_printout(&pktmaster[i], (uint8)arg_details); 5518 } 5519 cli_out("-----------------------------------------------------------" 5520 "---------------------\n"); 5521 5522 PTP_CLI_RESULT_RETURN(CMD_OK); 5523 5524 } else if (parse_cmp("BeST", arg, 0)) { 5525 parse_table_init(unit, &pt); 5526 parse_table_add(&pt, "Stack", PQ_INT, (void*)PTP_STACK_ID_DEFAULT, 5527 &arg_stack_id, NULL); 5528 parse_table_add(&pt, "Clock", PQ_INT, (void*)PTP_CLOCK_NUMBER_DEFAULT, 5529 &arg_clock_num, NULL); 5530 parse_table_add(&pt, "DeTaiLs", PQ_BOOL, (void*)0, &arg_details, NULL); 5531 if (parse_arg_eq(a, &pt) < 0) { 5532 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 5533 } 5534 parse_arg_eq_done(&pt); 5535 5536 PTP_IF_ERROR_RETURN(bcm_ptp_telecom_g8265_packet_master_best_get(unit, 5537 arg_stack_id, arg_clock_num, pktmaster)); 5538 5539 cli_out("\n"); 5540 cli_out("Telecom Profile Best Packet Master.\n"); 5541 cli_out("Unit: %d Stack: %d Clock: %d\n", 5542 unit, arg_stack_id, arg_clock_num); 5543 cli_out("-----------------------------------------------------------" 5544 "---------------------\n"); 5545 diag_telecom_pktmaster_printout(pktmaster, (uint8)arg_details); 5546 cli_out("-----------------------------------------------------------" 5547 "---------------------\n"); 5548 5549 PTP_CLI_RESULT_RETURN(CMD_OK); 5550 5551 } else { 5552 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5553 } 5554 5555 } else if (parse_cmp("OPTions", arg, 0)) { 5556 parse_table_init(unit, &pt); 5557 parse_table_add(&pt, "VERBose", PQ_BOOL, (void*)1, &arg_verbose, NULL); 5558 if (parse_arg_eq(a, &pt) < 0) { 5559 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 5560 } 5561 parse_arg_eq_done(&pt); 5562 5563 /* Set telecom profile verbose level (ON/OFF only at present). */ 5564 if (arg_verbose) { 5565 PTP_IF_ERROR_RETURN(_bcm_ptp_telecom_g8265_verbose_level_set((uint32)-1)); 5566 } else { 5567 PTP_IF_ERROR_RETURN(_bcm_ptp_telecom_g8265_verbose_level_set(0)); 5568 } 5569 5570 PTP_CLI_RESULT_RETURN(CMD_OK); 5571 5572 } 5573 5574 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5575 } 5576 5577 5578 /* PTP CTDEV */ 5579 #define PTP_CTDEV_USAGE \ 5580 "PTP CTDEV <subcommand> [...]\n" \ 5581 "\t PTP CTDEV OPTions [ENable=y/n] [VERBose=y/n]\n" \ 5582 "\t [ALPHA_Numerator=<value>] [ALPHA_Denominator=<value>]\n" 5583 5584 STATIC cmd_result_t 5585 cmd_ptp_ctdev(int unit, args_t *a) 5586 { 5587 parse_table_t pt; 5588 const char *arg = ARG_GET(a); 5589 int arg_enable; 5590 int arg_verbose; 5591 int arg_alpha_numerator; 5592 int arg_alpha_denominator; 5593 5594 if (!arg) { 5595 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5596 } else if (parse_cmp("OPTions", arg, 0)) { 5597 parse_table_init(unit, &pt); 5598 parse_table_add(&pt, "ENable", PQ_BOOL, (void*)1, &arg_enable, NULL); 5599 parse_table_add(&pt, "VERBose", PQ_BOOL, (void*)1, &arg_verbose, NULL); 5600 parse_table_add(&pt, "ALPHA_Numerator", PQ_INT, (void*)63, &arg_alpha_numerator, NULL); 5601 parse_table_add(&pt, "ALPHA_Denominator", PQ_INT, (void*)64, &arg_alpha_denominator, NULL); 5602 if (parse_arg_eq(a, &pt) < 0) { 5603 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 5604 } 5605 parse_arg_eq_done(&pt); 5606 5607 PTP_IF_ERROR_RETURN(bcm_ptp_ctdev_enable_set(unit, PTP_STACK_ID_DEFAULT, 5608 PTP_CLOCK_NUMBER_DEFAULT, arg_enable, 0)); 5609 PTP_IF_ERROR_RETURN(bcm_ptp_ctdev_verbose_set(unit, PTP_STACK_ID_DEFAULT, 5610 PTP_CLOCK_NUMBER_DEFAULT, arg_verbose)); 5611 PTP_IF_ERROR_RETURN(bcm_ptp_ctdev_alpha_set(unit, PTP_STACK_ID_DEFAULT, 5612 PTP_CLOCK_NUMBER_DEFAULT, arg_alpha_numerator, arg_alpha_denominator)); 5613 5614 if (arg_enable) { 5615 /* Register reference alarm callback function. */ 5616 PTP_IF_ERROR_RETURN(bcm_ptp_ctdev_alarm_callback_register(unit, PTP_STACK_ID_DEFAULT, 5617 PTP_CLOCK_NUMBER_DEFAULT, diag_ctdev_alarm_callback)); 5618 } else { 5619 /* Unregister reference alarm callback function. */ 5620 PTP_IF_ERROR_RETURN(bcm_ptp_ctdev_alarm_callback_unregister(unit, PTP_STACK_ID_DEFAULT, 5621 PTP_CLOCK_NUMBER_DEFAULT)); 5622 } 5623 5624 PTP_CLI_RESULT_RETURN(CMD_OK); 5625 } 5626 5627 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5628 } 5629 5630 5631 /* PTP MODULAR ... */ 5632 #define PTP_MODULAR_USAGE \ 5633 "PTP MODULAR <subcommand> [...]\n" \ 5634 "\t PTP MODULAR GET\n" \ 5635 "\t PTP MODULAR SET [ENable=y/n] [VERBose=y/n]\n" \ 5636 "\t [PHYTS=y/n] [FrameSyncPIN=<pin>] [PBM=<port bitmap>]\n" 5637 5638 STATIC cmd_result_t 5639 cmd_ptp_modular(int unit, args_t *a) 5640 { 5641 int rv; 5642 5643 parse_table_t pt; 5644 const char *arg = ARG_GET(a); 5645 int arg_enable; 5646 uint32 flags; 5647 int arg_verbose; 5648 int arg_phyts; 5649 int arg_framesync_pin; 5650 char *arg_pbmp_str = 0; 5651 bcm_pbmp_t arg_pbmp; 5652 5653 if (!arg) { 5654 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5655 } else if (parse_cmp("GET", arg, 0)) { 5656 PTP_IF_ERROR_RETURN(bcm_ptp_modular_enable_get(unit, PTP_STACK_ID_DEFAULT, 5657 PTP_CLOCK_NUMBER_DEFAULT, &arg_enable, &flags)); 5658 PTP_IF_ERROR_RETURN(bcm_ptp_modular_verbose_get(unit, PTP_STACK_ID_DEFAULT, 5659 PTP_CLOCK_NUMBER_DEFAULT, &arg_verbose)); 5660 PTP_IF_ERROR_RETURN(bcm_ptp_modular_phyts_get(unit, PTP_STACK_ID_DEFAULT, 5661 PTP_CLOCK_NUMBER_DEFAULT, &arg_phyts, &arg_framesync_pin)); 5662 5663 cli_out("\n"); 5664 cli_out("Modular System (Control Parameters and Options).\n"); 5665 cli_out("Unit: %d Stack: %d Clock: %d\n", 5666 unit, PTP_STACK_ID_DEFAULT, PTP_CLOCK_NUMBER_DEFAULT); 5667 cli_out("-----------------------------------------------------------" 5668 "---------------------\n"); 5669 cli_out("Enable : %s\n", arg_enable ? "Y":"N"); 5670 cli_out("Verbose: %s\n", arg_verbose ? "Y":"N"); 5671 cli_out("PHY TS : %s\n", arg_phyts ? "Y":"N"); 5672 5673 PTP_CLI_RESULT_RETURN(CMD_OK); 5674 5675 } else if (parse_cmp("SET", arg, 0)) { 5676 parse_table_init(unit, &pt); 5677 parse_table_add(&pt, "ENable", PQ_BOOL, (void*)1, &arg_enable, NULL); 5678 parse_table_add(&pt, "VERBose", PQ_BOOL, (void*)1, &arg_verbose, NULL); 5679 parse_table_add(&pt, "PHYTS", PQ_BOOL, (void*)0, &arg_phyts, NULL); 5680 parse_table_add(&pt, "FrameSyncPIN", PQ_INT, (void*)3, &arg_framesync_pin, NULL); 5681 parse_table_add(&pt, "PBM", PQ_STRING, (void*)"", &arg_pbmp_str, NULL); 5682 if (parse_arg_eq(a, &pt) < 0) { 5683 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 5684 } 5685 5686 rv = parse_bcm_pbmp(unit, arg_pbmp_str, &arg_pbmp); 5687 parse_arg_eq_done(&pt); 5688 5689 if (BCM_E_NONE == rv) { 5690 /* Valid port bitmap. Update port bitmap for PHY synchronization. */ 5691 PTP_IF_ERROR_RETURN(bcm_ptp_modular_portbitmap_set(unit, PTP_STACK_ID_DEFAULT, 5692 PTP_CLOCK_NUMBER_DEFAULT, arg_pbmp)); 5693 } 5694 5695 PTP_IF_ERROR_RETURN(bcm_ptp_modular_enable_set(unit, PTP_STACK_ID_DEFAULT, 5696 PTP_CLOCK_NUMBER_DEFAULT, arg_enable, 0)); 5697 PTP_IF_ERROR_RETURN(bcm_ptp_modular_verbose_set(unit, PTP_STACK_ID_DEFAULT, 5698 PTP_CLOCK_NUMBER_DEFAULT, arg_verbose)); 5699 PTP_IF_ERROR_RETURN(bcm_ptp_modular_phyts_set(unit, PTP_STACK_ID_DEFAULT, 5700 PTP_CLOCK_NUMBER_DEFAULT, arg_phyts, arg_framesync_pin)); 5701 5702 PTP_CLI_RESULT_RETURN(CMD_OK); 5703 } else { 5704 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5705 } 5706 5707 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5708 } 5709 5710 FILE * volatile tsfifo_fp = NULL; 5711 5712 int timestamp_cb(int unit, void *user_data, uint32 *cb_data_ptr, bcm_time_capture_cb_type_t status) 5713 { 5714 /* Sample handling of retreived timestamp FIFO entries */ 5715 uint16 num_entries = 0; 5716 5717 num_entries = *cb_data_ptr; 5718 5719 if (tsfifo_fp) { 5720 if (sal_fwrite(cb_data_ptr, 4, 1, tsfifo_fp) != 1) { 5721 cli_out("\nError writing to file\n"); 5722 } 5723 num_entries = soc_ntohl(*cb_data_ptr); 5724 /* cli_out("\n num_entries[%d : %08x]", num_entries, *cb_data_ptr);*/ 5725 cb_data_ptr++; 5726 while(num_entries-- > 0) { 5727 if (sal_fwrite(cb_data_ptr, 4, 1, tsfifo_fp) != 1) { 5728 cli_out("\n Error writing to file\n"); 5729 } 5730 /* cli_out("\n word_1[%08x]", *cb_data_ptr); */ 5731 cb_data_ptr++; 5732 if (sal_fwrite(cb_data_ptr, 4, 1, tsfifo_fp) != 1) { 5733 cli_out("\nError writing to file\n"); 5734 } 5735 /* cli_out("\t word_2[%08x]\n", *cb_data_ptr); */ 5736 cb_data_ptr++; 5737 } 5738 } 5739 return BCM_E_NONE; 5740 } 5741 5742 STATIC int 5743 bcm_time_ts_fifo_capture_start(int unit) 5744 { 5745 int rv = 0; 5746 bcm_time_capture_cb_type_t cb_type; 5747 5748 if(!tsfifo_fp) { 5749 tsfifo_fp = sal_fopen("Test/ts_fifo.log", "w+"); 5750 if (!tsfifo_fp) { 5751 cli_out("\n Error: Unable to open file\n"); 5752 return BCM_E_FAIL; 5753 } else { 5754 cli_out("\n File opened \n"); 5755 } 5756 } 5757 cb_type = bcmTimeCapturetFill; 5758 rv = bcm_time_capture_cb_register (unit, 0, cb_type, timestamp_cb, NULL); 5759 return rv; 5760 } 5761 5762 STATIC int 5763 bcm_time_ts_fifo_capture_stop(int unit) 5764 { 5765 int rv = 0; 5766 bcm_time_capture_cb_type_t cb_type; 5767 5768 cb_type = bcmTimeCapturetFill; 5769 rv = bcm_time_capture_cb_unregister (unit, 0, cb_type); 5770 5771 if (tsfifo_fp) { 5772 sal_fclose((FILE *)tsfifo_fp); 5773 cli_out("\n Closing file \n"); 5774 tsfifo_fp = NULL; 5775 } 5776 return rv; 5777 } 5778 5779 /* PTP TsFifo */ 5780 #define PTP_TSFIFO_USAGE \ 5781 "PTP TsFifo <subcommand> [...]\n" \ 5782 "\t PTP TsFifo TimeInit\n" \ 5783 "\t PTP TsFifo CaptureSTART\n" \ 5784 "\t PTP TsFifo CaptureSTOP\n" 5785 5786 STATIC cmd_result_t 5787 cmd_ptp_ts_fifo(int unit, args_t *a) 5788 { 5789 int rv=0; 5790 const char *arg = ARG_GET(a); 5791 5792 if (!arg) { 5793 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5794 } else if (parse_cmp("TimeInit", arg, 0)) { 5795 rv = bcm_time_init(unit); 5796 cli_out("\n bcm_time_init returned [%d]", rv); 5797 PTP_CLI_RESULT_RETURN(CMD_OK); 5798 } else if (parse_cmp("CaptureSTART", arg, 0)) { 5799 bcm_time_ts_fifo_capture_start(unit); 5800 PTP_CLI_RESULT_RETURN(CMD_OK); 5801 } else if (parse_cmp("CaptureSTOP", arg, 0)) { 5802 bcm_time_ts_fifo_capture_stop(unit); 5803 PTP_CLI_RESULT_RETURN(CMD_OK); 5804 } 5805 5806 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5807 } 5808 5809 /* PTP DIAGshell */ 5810 #define PTP_DIAGSHELL_USAGE \ 5811 "PTP DIAGshell <subcommand> [...]\n" \ 5812 "\t PTP DIAGshell OPTions [VERBose=y/n]\n" \ 5813 "\t PTP DIAGshell SYNC\n" 5814 5815 STATIC cmd_result_t 5816 cmd_ptp_diagshell(int unit, args_t *a) 5817 { 5818 parse_table_t pt; 5819 const char *arg = ARG_GET(a); 5820 5821 if (!arg) { 5822 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5823 } else if (parse_cmp("OPTions", arg, 0)) { 5824 parse_table_init(unit, &pt); 5825 parse_table_add(&pt, "VERBose", PQ_BOOL, INT_TO_PTR(verboseCLI), &verboseCLI, NULL); 5826 parse_table_add(&pt, "VerboseEvents", PQ_INT, INT_TO_PTR(verboseEvents), &verboseEvents, NULL); 5827 if (parse_arg_eq(a, &pt) < 0) { 5828 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 5829 } 5830 parse_arg_eq_done(&pt); 5831 PTP_CLI_RESULT_RETURN(CMD_OK); 5832 } else if (parse_cmp("SYNC", arg, 0)) { 5833 PTP_IF_ERROR_RETURN(bcm_ptp_clock_time_get(unit, cur_stack_id, cur_clock_num, &diagshell_sync.ptp_time)); 5834 diagshell_sync.host_time = sal_time(); 5835 diagshell_sync.synced = 1; 5836 5837 PTP_CLI_RESULT_RETURN(CMD_OK); 5838 } 5839 5840 PTP_CLI_RESULT_RETURN(CMD_USAGE); 5841 } 5842 5843 5844 /* TDPLL INSTANCE ... */ 5845 /* We divide the string because pedantic compiler doesn't allow strings longer then 509 characters */ 5846 #define TDPLL_INSTANCE_USAGE_1 \ 5847 "TDPLL INSTance <subcommand> [...]\n" \ 5848 "\t TDPLL INSTance [show] [<index>]\n" \ 5849 "\t I/i: Enabled/Disabled Input\n" \ 5850 "\t O/o: Enabled/disabled output\n" \ 5851 "\t *: Selected\n" 5852 #define TDPLL_INSTANCE_USAGE_2 \ 5853 "\t TDPLL INSTance Get <index>\n" \ 5854 "\t TDPLL INSTance Set <index> INputMaSK=<hex> OUTputMaSK=<hex>\n" \ 5855 "\t PHaseMODE=<|NONE|PBO|PHaseSLEW|> PHaseOFFSET=<value>\n" \ 5856 "\t DPLLBandWidth=<bandwidth>\n" \ 5857 "\t where <bandwidth> = | 0.01Hz | 0.05Hz | 0.1Hz | 0.5Hz |\n" \ 5858 "\t | 1Hz | 5Hz | 10Hz |\n" 5859 5860 5861 STATIC cmd_result_t 5862 tdpll_instance_show(int unit, int low_idx, int high_idx) 5863 { 5864 bcm_tdpll_dpll_bindings_t bindings; 5865 bcm_tdpll_dpll_bandwidth_t bandwidth; 5866 bcm_tdpll_dpll_phase_control_t phase_control; 5867 uint32 input_mask; 5868 uint32 output_mask; 5869 5870 int dpll_index, best_input, num_dplls, i; 5871 int dpll_refs[TDPLL_DPLL_INSTANCE_NUM_MAX]; 5872 5873 uint32 bwhz_dec = 0; 5874 uint32 bwhz_frac = 0; 5875 5876 #if defined (BCM_APACHE_SUPPORT) 5877 int num_io = 13, ptp_io_num = 8, alt_ptp_input_idx = 9; 5878 /* mappings from our print index to input or output bit index. 1000->none */ 5879 const int input_idx[15] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 1000, 1000, 1000, 1000, 1000, 1000}; 5880 const int output_idx[15] = {5, 6, 7, 8, 9, 10, 1000, 1000, 4, 0, 1, 2, 3, 11, 12}; 5881 5882 const char *padding[15] = {" ", " ", " ", " ", " ", " ", /* GPIO 0-5 */ 5883 " ", " ", " ", /* SE1, SE2, 1588 */ 5884 " ", " ", " ", " ", " ", " "};/* BS0, BS1, SLCPLL/XGPLL0, MLCPLL/XGPLL1, XGPLL2, XGPLL3 */ 5885 5886 if (SOC_IS_APACHE(unit)) { 5887 cli_out("# GP0 GP1 GP2 GP3 GP4 GP5 SE1 SE2 1588 BS0 BS1 XGPLL0 XGPLL1 XGPLL2 XGPLL3 BW PBO\n"); 5888 } else { 5889 cli_out("# GP0 GP1 GP2 GP3 GP4 GP5 SE1 SE2 1588 BS0 BS1 S-PLL M-PLL BW PBO\n"); 5890 } 5891 #elif defined (BCM_QAX_SUPPORT) 5892 int num_io = 13, ptp_io_num = 8, alt_ptp_input_idx = 9; 5893 /* mappings from our print index to input or output bit index. 1000->none */ 5894 const int input_idx[14] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 1000, 1000, 1000, 1000, 1000}; 5895 const int output_idx[14] = {5, 6, 7, 8, 9, 10, 1000, 1000, 4, 0, 1, 2, 3, 11}; 5896 5897 const char *padding[14] = {" ", " ", " ", " ", " ", " ", /* GPIO 0-5 */ 5898 " ", " ", " ", /* SE1, SE2, 1588 */ 5899 " ", " ", " ", " ", " "}; /* BS0, BS1, PML0, PML1, PMH */ 5900 5901 if (SOC_IS_QUX(unit)) { 5902 cli_out("# TSGP0 TSGP1 GP0 GP1 - - SE1 SE2 1588 BS0 BS1 PMLPLL PMXPLL BW PBO\n"); 5903 } else if (SOC_IS_QAX(unit)) { 5904 cli_out("# GP0 GP1 GP2 GP3 GP4 GP5 SE1 SE2 1588 BS0 BS1 PML0PLL PML1PLL PMHPLL BW PBO\n"); 5905 } else { 5906 cli_out("# GP0 GP1 GP2 GP3 GP4 GP5 SE1 SE2 1588 BS0 BS1 S-PLL M-PLL BW PBO\n"); 5907 } 5908 5909 5910 #else 5911 const int num_io = 13, ptp_io_num = 8, alt_ptp_input_idx = 9; 5912 /* mappings from our print index to input or output bit index. 1000->none */ 5913 const int input_idx[13] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 1000, 1000, 1000, 1000}; 5914 const int output_idx[13] = {5, 6, 7, 8, 9, 10, 1000, 1000, 4, 0, 1, 2, 3}; 5915 const char *padding[13] = {" ", " ", " ", " ", " ", " ", /* GPIO 0-5 */ 5916 " ", " ", " ", /* SE1, SE2, 1588 */ 5917 " ", " ", " ", " "}; /* BS0, BS1, SLCPLL, MLCPLL */ 5918 5919 cli_out("# GP0 GP1 GP2 GP3 GP4 GP5 SE1 SE2 1588 BS0 BS1 S-PLL M-PLL BW PBO\n"); 5920 #endif 5921 5922 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_reference_get( 5923 unit, 0, TDPLL_DPLL_INSTANCE_NUM_MAX, dpll_refs, &num_dplls)); 5924 5925 for (dpll_index = low_idx; dpll_index < high_idx; ++dpll_index) { 5926 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_bindings_get(unit, 0, dpll_index, &bindings)); 5927 5928 5929 input_mask = bindings.input_clocks[0]; 5930 5931 output_mask = bindings.output_clocks[0]; 5932 5933 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_bandwidth_get(unit, 0, dpll_index, &bandwidth)); 5934 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_phase_control_get(unit, 0, dpll_index, &phase_control)); 5935 5936 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_best_get(unit, 0, dpll_index, &best_input)); 5937 5938 cli_out("%d:", dpll_index); 5939 5940 #if defined (BCM_APACHE_SUPPORT) 5941 if (SOC_IS_APACHE(unit)) { 5942 num_io = 15; 5943 } 5944 #elif defined (BCM_QAX_SUPPORT) 5945 if (SOC_IS_QUX(unit)) { 5946 /* retain num_io as default i.e., 13 */ 5947 } else if (SOC_IS_QAX(unit)) { 5948 num_io = 14; 5949 } 5950 #endif 5951 for (i = 0; i < num_io; ++i) { 5952 const char input_char[3] = {'-', 'i', 'I'}; 5953 const char output_char[3] = {'-', 'o', 'O'}; 5954 const char reference_char[4] = {' ', '+', '*', '*'}; 5955 int is_best = (input_idx[i] == best_input); 5956 int is_ref = (input_idx[i] == dpll_refs[dpll_index]); 5957 int reference_idx; 5958 int enabled, input_status = 0, output_status = 0; 5959 5960 /* Calculate input and output status */ 5961 if (input_mask & (1 << input_idx[i])) { 5962 int enabled = 0; 5963 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_enable_get(unit, 0, input_idx[i], &enabled)); 5964 input_status = 1 + enabled; 5965 } else { 5966 input_status = 0; 5967 } 5968 if (i == ptp_io_num) { 5969 /* For the 1588 column, override the 1588-Freq with 1588-Phase if in use */ 5970 /* Not ideal, but the "tdpll input" command can be used to disambiguate */ 5971 if (input_mask & (1 << alt_ptp_input_idx)) { 5972 int alt_enabled = 0; 5973 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_enable_get( 5974 unit, 0, alt_ptp_input_idx, &alt_enabled)); 5975 if (input_status < 1 + alt_enabled) { 5976 input_status = 1 + alt_enabled; 5977 } 5978 5979 if (alt_ptp_input_idx == best_input) { 5980 is_best = 1; 5981 } 5982 if (alt_ptp_input_idx == dpll_refs[dpll_index]) { 5983 is_ref = 1; 5984 } 5985 } 5986 } 5987 reference_idx = is_ref * 2 + is_best; /* '*' if active reference, '+' if best but not active */ 5988 if (output_mask & (1 << output_idx[i])) { 5989 PTP_IF_ERROR_RETURN(bcm_tdpll_output_clock_enable_get(unit, 0, output_idx[i], &enabled)); 5990 output_status = 1 + enabled; 5991 } else { 5992 output_status = 0; 5993 } 5994 /* Display input and output status with possible '/' */ 5995 if (input_status) { 5996 if (output_status) { 5997 cli_out("%s%c/%c%c", padding[i], input_char[input_status], output_char[output_status], 5998 reference_char[reference_idx]); 5999 } else { 6000 cli_out("%s %c%c ", padding[i], input_char[input_status], reference_char[reference_idx]); 6001 } 6002 } else { 6003 cli_out("%s %c%c ", padding[i], output_char[output_status], reference_char[reference_idx]); 6004 } 6005 } 6006 6007 /* Bandwidth printout as x.yz. (i.e. one-hundredth Hz precision). */ 6008 switch (bandwidth.units) { 6009 case bcm_tdpll_dpll_bandwidth_mHz: 6010 bwhz_dec = bandwidth.value / 1000; 6011 bwhz_frac = ((bandwidth.value % 1000) + 5)/10; 6012 break; 6013 case bcm_tdpll_dpll_bandwidth_Hz: 6014 bwhz_dec = bandwidth.value; 6015 bwhz_frac = 0; 6016 break; 6017 case bcm_tdpll_dpll_bandwidth_kHz: 6018 bwhz_dec = bandwidth.value * 1000; 6019 bwhz_frac = 0; 6020 break; 6021 default: 6022 bwhz_dec = 0; 6023 bwhz_frac = 0; 6024 break; 6025 } 6026 cli_out("%3u.%02u", (unsigned)bwhz_dec, (unsigned)bwhz_frac); 6027 6028 switch (phase_control.mode) { 6029 case bcm_tdpll_dpll_phase_mode_none: 6030 cli_out(" Off "); 6031 break; 6032 case bcm_tdpll_dpll_phase_mode_pbo: 6033 cli_out(" On "); 6034 break; 6035 case bcm_tdpll_dpll_phase_mode_pboslew: 6036 cli_out(" Slew"); 6037 break; 6038 } 6039 cli_out("\n"); 6040 } 6041 cli_out("\n"); 6042 6043 PTP_CLI_RESULT_RETURN(CMD_OK); 6044 } 6045 6046 6047 STATIC cmd_result_t 6048 cmd_tdpll_instance(int unit, args_t *a) 6049 { 6050 parse_table_t pt; 6051 const char *arg = ARG_GET(a); 6052 6053 int invalid_value = 0x7fffffff; 6054 6055 int arg_dpll_index = -1; 6056 6057 int arg_input_mask = 0; 6058 int arg_output_mask = 0; 6059 6060 char *arg_phase_mode_str[4] = {"NONE", "PBO", "PHaseSLEW", 0}; 6061 int arg_phase_mode_index = invalid_value; 6062 int arg_phase_offset = 0; 6063 bcm_tdpll_dpll_phase_control_t arg_phase_control; 6064 char **input_str = NULL; 6065 6066 char *arg_bandwidth_str[8] = {"0.01Hz", "0.05Hz", "0.1Hz", "0.5Hz", "1Hz", "4Hz", "5Hz", "10Hz"}; 6067 int arg_bandwidth_index = invalid_value; 6068 bcm_tdpll_dpll_bandwidth_t arg_dpll_bandwidth_array[8] = 6069 {{10, bcm_tdpll_dpll_bandwidth_mHz}, 6070 {50, bcm_tdpll_dpll_bandwidth_mHz}, 6071 {100, bcm_tdpll_dpll_bandwidth_mHz}, 6072 {500, bcm_tdpll_dpll_bandwidth_mHz}, 6073 {1, bcm_tdpll_dpll_bandwidth_Hz}, 6074 {4, bcm_tdpll_dpll_bandwidth_Hz}, 6075 {5, bcm_tdpll_dpll_bandwidth_Hz}, 6076 {10, bcm_tdpll_dpll_bandwidth_Hz}}; 6077 6078 char *input_str_common[TDPLL_INPUT_CLOCK_NUM_MAX] = 6079 {"GPIO0 ", "GPIO1 ", "GPIO2 ", "GPIO3 ", "GPIO4 ", "GPIO5 ", 6080 "SyncE1", "SyncE2", "1588-Freq", "1588-Phase"}; 6081 6082 #if defined (BCM_QAX_SUPPORT) 6083 char *input_str_qux[TDPLL_INPUT_CLOCK_NUM_MAX] = 6084 {"TSGPIO0 ", "TSGPIO1 ", "GPIO0 ", "GPIO1 ", " - ", " - ", 6085 "SyncE1", "SyncE2", "1588-Freq", "1588-Phase"}; 6086 #endif 6087 6088 #if defined (BCM_APACHE_SUPPORT) 6089 char *output_str_ap[TDPLL_OUTPUT_CLOCK_NUM_MAX] = 6090 {"BroadSync0 ", "BroadSync1 ", "XgPll0 ", "XgPll1 ", 6091 "1588-Hybrid ", "GPIO0", "GPIO1", "GPIO2", "GPIO3", "GPIO4", "GPIO5", "XgPll2 ", "XgPll3 "}; 6092 #endif 6093 #if defined (BCM_QAX_SUPPORT) 6094 char *output_str_qax[TDPLL_OUTPUT_CLOCK_NUM_MAX] = 6095 {"BroadSync0 ", "BroadSync1 ", "Pml0Pll ", "Pml1Pll ", 6096 "1588-Hybrid ", "GPIO0", "GPIO1", "GPIO2", "GPIO3", "GPIO4", "GPIO5", "PmhPll "}; 6097 char *output_str_qux[TDPLL_OUTPUT_CLOCK_NUM_MAX] = 6098 {"BroadSync0 ", "BroadSync1 ", "PmlPll ", "PmxPll ", 6099 "1588-Hybrid ", "TSGPIO0", "TSGPIO1", "GPIO0", "GPIO1", " - ", " - "}; 6100 #endif 6101 char *output_str[TDPLL_OUTPUT_CLOCK_NUM_MAX] = 6102 {"BroadSync0 ", "BroadSync1 ", "SerDesLCPLL ", "MasterLCPLL ", 6103 "1588-Hybrid ", "GPIO0", "GPIO1", "GPIO2", "GPIO3", "GPIO4", "GPIO5"}; 6104 6105 bcm_tdpll_dpll_bindings_t arg_bindings; 6106 bcm_tdpll_dpll_bandwidth_t arg_dpll_bandwidth = {1, bcm_tdpll_dpll_bandwidth_Hz}; 6107 6108 uint32 input_mask; 6109 uint32 output_mask; 6110 int start_index = 0, end_index = TDPLL_DPLL_INSTANCE_NUM_MAX; 6111 6112 input_str = input_str_common; 6113 #if defined (BCM_QAX_SUPPORT) 6114 if (SOC_IS_QUX(unit)) { 6115 input_str = input_str_qux; 6116 } 6117 #endif 6118 6119 #if defined (BCM_APACHE_SUPPORT) || defined (BCM_QAX_SUPPORT) 6120 if (SOC_IS_QUX(unit)) { 6121 end_index = TDPLL_DPLL_INSTANCE_NUM_MAX - 2; 6122 } else if (SOC_IS_APACHE(unit) || SOC_IS_QAX(unit)) { 6123 /* Retain end_index */ 6124 } else { 6125 end_index = TDPLL_DPLL_INSTANCE_NUM_MAX - 2; 6126 } 6127 #else 6128 end_index = TDPLL_DPLL_INSTANCE_NUM_MAX - 2; 6129 6130 #endif 6131 6132 if (arg) { 6133 char *dpll_index_str = ARG_GET(a); 6134 if (dpll_index_str) { 6135 if (!isint(dpll_index_str)) { 6136 cli_out("%s INSTance show/Get/Set: Invalid DPLL index '%s'\n", ARG_CMD(a), dpll_index_str); 6137 cli_out(TDPLL_INSTANCE_USAGE_1); 6138 cli_out(TDPLL_INSTANCE_USAGE_2); 6139 return CMD_FAIL; 6140 } 6141 arg_dpll_index = parse_integer(dpll_index_str); 6142 } 6143 } 6144 6145 if (!arg || parse_cmp("show", arg, 0)) { 6146 if (arg_dpll_index >= 0) { 6147 start_index = arg_dpll_index; 6148 end_index = arg_dpll_index + 1; 6149 } 6150 6151 return tdpll_instance_show(unit, start_index, end_index); 6152 } else if (parse_cmp("Get", arg, 0)) { 6153 if (arg_dpll_index < 0) { 6154 cli_out("%s INSTance Get: No DPLL index specified\n", ARG_CMD(a)); 6155 return(CMD_FAIL); 6156 } 6157 6158 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_bindings_get( 6159 unit, 0, arg_dpll_index, &arg_bindings)); 6160 6161 input_mask = arg_bindings.input_clocks[0]; 6162 6163 output_mask = arg_bindings.output_clocks[0]; 6164 6165 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_bandwidth_get( 6166 unit, 0, arg_dpll_index, &arg_dpll_bandwidth)); 6167 6168 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_phase_control_get( 6169 unit, 0, arg_dpll_index, &arg_phase_control)); 6170 6171 cli_out("\n"); 6172 cli_out("T-DPLL DPLL Instance Configuration.\n"); 6173 cli_out("Unit: %d Stack: %d\n", 6174 unit, 0); 6175 cli_out("-----------------------------------------------------------" 6176 "---------------------\n"); 6177 cli_out("DPLL : %d\n", arg_dpll_index); 6178 cli_out("\n"); 6179 cli_out("Inputs : 0x%08x\n", input_mask); 6180 cli_out(" | %s [%s] | %s [%s] | %s [%s] | %s [%s] |\n" 6181 " | %s [%s] | %s [%s] | %s [%s] | %s [%s] |\n" 6182 " | %s [%s] | %s [%s] |\n", 6183 input_str[0], input_mask & (1 << 0) ? "x":" ", 6184 input_str[1], input_mask & (1 << 1) ? "x":" ", 6185 input_str[2], input_mask & (1 << 2) ? "x":" ", 6186 input_str[3], input_mask & (1 << 3) ? "x":" ", 6187 input_str[4], input_mask & (1 << 4) ? "x":" ", 6188 input_str[5], input_mask & (1 << 5) ? "x":" ", 6189 input_str[6], input_mask & (1 << 6) ? "x":" ", 6190 input_str[7], input_mask & (1 << 7) ? "x":" ", 6191 input_str[8], input_mask & (1 << 8) ? "x":" ", 6192 input_str[9], input_mask & (1 << 9) ? "x":" "); 6193 cli_out("\n"); 6194 cli_out("Outputs : 0x%08x\n", output_mask); 6195 #if defined (BCM_APACHE_SUPPORT) 6196 if (SOC_IS_APACHE(unit)) { 6197 cli_out(" | %s [%s] | %s [%s] |\n" 6198 " | %s [%s] | %s [%s] |\n" 6199 " | %s [%s] | %s [%s] | %s [%s] | %s [%s] |\n" 6200 " | %s [%s] | %s [%s] | %s [%s] | %s [%s] | %s [%s] |\n", 6201 output_str_ap[0], output_mask & (1 << 0) ? "x":" ", 6202 output_str_ap[1], output_mask & (1 << 1) ? "x":" ", 6203 output_str_ap[2], output_mask & (1 << 2) ? "x":" ", 6204 output_str_ap[3], output_mask & (1 << 3) ? "x":" ", 6205 output_str_ap[4], output_mask & (1 << 4) ? "x":" ", 6206 output_str_ap[5], output_mask & (1 << 5) ? "x":" ", 6207 output_str_ap[6], output_mask & (1 << 6) ? "x":" ", 6208 output_str_ap[7], output_mask & (1 << 7) ? "x":" ", 6209 output_str_ap[8], output_mask & (1 << 8) ? "x":" ", 6210 output_str_ap[9], output_mask & (1 << 9) ? "x":" ", 6211 output_str_ap[10], output_mask & (1 << 10) ? "x":" ", 6212 output_str_ap[11], output_mask & (1 << 11) ? "x":" ", 6213 output_str_ap[12], output_mask & (1 << 12) ? "x":" "); 6214 } else 6215 #endif 6216 #if defined(BCM_QAX_SUPPORT) 6217 if (SOC_IS_QUX(unit)) { 6218 cli_out(" | %s [%s] | %s [%s] |\n" 6219 " | %s [%s] | %s [%s] |\n" 6220 " | %s [%s] | %s [%s] | %s [%s] |\n" 6221 " | %s [%s] | %s [%s] | %s [%s] | %s [%s] |\n", 6222 output_str_qux[0], output_mask & (1 << 0) ? "x":" ", 6223 output_str_qux[1], output_mask & (1 << 1) ? "x":" ", 6224 output_str_qux[2], output_mask & (1 << 2) ? "x":" ", 6225 output_str_qux[3], output_mask & (1 << 3) ? "x":" ", 6226 output_str_qux[4], output_mask & (1 << 4) ? "x":" ", 6227 output_str_qux[5], output_mask & (1 << 5) ? "x":" ", 6228 output_str_qux[6], output_mask & (1 << 6) ? "x":" ", 6229 output_str_qux[7], output_mask & (1 << 7) ? "x":" ", 6230 output_str_qux[8], output_mask & (1 << 8) ? "x":" ", 6231 output_str_qux[9], output_mask & (1 << 9) ? "x":" ", 6232 output_str_qux[10], output_mask & (1 << 10) ? "x":" "); 6233 } else if (SOC_IS_QAX(unit)) { 6234 cli_out(" | %s [%s] | %s [%s] |\n" 6235 " | %s [%s] | %s [%s] |\n" 6236 " | %s [%s] | %s [%s] | %s [%s] | %s [%s] |\n" 6237 " | %s [%s] | %s [%s] | %s [%s] | %s [%s] |\n", 6238 output_str_qax[0], output_mask & (1 << 0) ? "x":" ", 6239 output_str_qax[1], output_mask & (1 << 1) ? "x":" ", 6240 output_str_qax[2], output_mask & (1 << 2) ? "x":" ", 6241 output_str_qax[3], output_mask & (1 << 3) ? "x":" ", 6242 output_str_qax[4], output_mask & (1 << 4) ? "x":" ", 6243 output_str_qax[5], output_mask & (1 << 5) ? "x":" ", 6244 output_str_qax[6], output_mask & (1 << 6) ? "x":" ", 6245 output_str_qax[7], output_mask & (1 << 7) ? "x":" ", 6246 output_str_qax[8], output_mask & (1 << 8) ? "x":" ", 6247 output_str_qax[9], output_mask & (1 << 9) ? "x":" ", 6248 output_str_qax[10], output_mask & (1 << 10) ? "x":" ", 6249 output_str_qax[11], output_mask & (1 << 11) ? "x":" "); 6250 } else 6251 #endif 6252 { 6253 cli_out(" | %s [%s] | %s [%s] |\n" 6254 " | %s [%s] | %s [%s] |\n" 6255 " | %s [%s] | %s [%s] | %s [%s] |\n" 6256 " | %s [%s] | %s [%s] | %s [%s] | %s [%s] |\n", 6257 output_str[0], output_mask & (1 << 0) ? "x":" ", 6258 output_str[1], output_mask & (1 << 1) ? "x":" ", 6259 output_str[2], output_mask & (1 << 2) ? "x":" ", 6260 output_str[3], output_mask & (1 << 3) ? "x":" ", 6261 output_str[4], output_mask & (1 << 4) ? "x":" ", 6262 output_str[5], output_mask & (1 << 5) ? "x":" ", 6263 output_str[6], output_mask & (1 << 6) ? "x":" ", 6264 output_str[7], output_mask & (1 << 7) ? "x":" ", 6265 output_str[8], output_mask & (1 << 8) ? "x":" ", 6266 output_str[9], output_mask & (1 << 9) ? "x":" ", 6267 output_str[10], output_mask & (1 << 10) ? "x":" "); 6268 } 6269 6270 cli_out("\n"); 6271 cli_out("Phase Mode : %s (%d) %d ns\n", 6272 arg_phase_control.mode == bcm_tdpll_dpll_phase_mode_none ? 6273 "None" : (arg_phase_control.mode == bcm_tdpll_dpll_phase_mode_pbo ? 6274 "PBO" : (arg_phase_control.mode == bcm_tdpll_dpll_phase_mode_pboslew ? 6275 "PBO + Phase Slew" : "Unknown")), arg_phase_control.mode, arg_phase_control.offset_ns); 6276 cli_out("Bandwidth : %d %s\n", 6277 arg_dpll_bandwidth.value, 6278 arg_dpll_bandwidth.units == bcm_tdpll_dpll_bandwidth_mHz ? 6279 "mHz" : (arg_dpll_bandwidth.units == bcm_tdpll_dpll_bandwidth_Hz ? 6280 "Hz" : (arg_dpll_bandwidth.units == bcm_tdpll_dpll_bandwidth_kHz ? 6281 "kHz" : "Unknown"))); 6282 cli_out("\n"); 6283 6284 PTP_CLI_RESULT_RETURN(CMD_OK); 6285 6286 } else if (parse_cmp("Set", arg, 0)) { 6287 if (arg_dpll_index < 0) { 6288 cli_out("%s INSTance Set: No DPLL index specified\n", ARG_CMD(a)); 6289 return(CMD_FAIL); 6290 } 6291 parse_table_init(unit, &pt); 6292 parse_table_add(&pt, "INputMaSK", PQ_HEX, (void*)(size_t)invalid_value, 6293 &arg_input_mask, NULL); 6294 parse_table_add(&pt, "OUTputMaSK", PQ_HEX, (void*)(size_t)invalid_value, 6295 &arg_output_mask, NULL); 6296 parse_table_add(&pt, "DPLLBandWidth", PQ_MULTI | PQ_DFL, 0, 6297 &arg_bandwidth_index, arg_bandwidth_str); 6298 parse_table_add(&pt, "PHaseMODE", PQ_MULTI | PQ_DFL, 0, 6299 &arg_phase_mode_index, arg_phase_mode_str); 6300 parse_table_add(&pt, "PHaseOFFSET", PQ_INT, (void*)0, &arg_phase_offset, NULL); 6301 6302 if (parse_arg_eq(a, &pt) < 0) { 6303 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 6304 } 6305 parse_arg_eq_done(&pt); 6306 6307 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_bindings_get( 6308 unit, 0, arg_dpll_index, &arg_bindings)); 6309 6310 if (arg_input_mask != invalid_value) { 6311 6312 arg_bindings.input_clocks[0] = (uint32)arg_input_mask; 6313 /*arg_bindings.input_clocks[1] = 0; 6314 arg_bindings.input_clocks[2] = 0;*/ 6315 } 6316 6317 if (arg_output_mask != invalid_value) { 6318 6319 arg_bindings.output_clocks[0] = (uint32)arg_output_mask; 6320 /*arg_bindings.output_clocks[1] = 0; 6321 arg_bindings.output_clocks[2] = 0;*/ 6322 } 6323 6324 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_bindings_set( 6325 unit, 0, arg_dpll_index, &arg_bindings)); 6326 6327 if (arg_bandwidth_index != invalid_value) { 6328 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_bandwidth_set( 6329 unit, 0, arg_dpll_index, &arg_dpll_bandwidth_array[arg_bandwidth_index])); 6330 } 6331 6332 if (arg_phase_mode_index != invalid_value) { 6333 arg_phase_control.mode = (bcm_tdpll_dpll_phase_mode_t)arg_phase_mode_index; 6334 arg_phase_control.offset_ns = arg_phase_offset; 6335 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_phase_control_set(unit, 0, 6336 arg_dpll_index, &arg_phase_control)); 6337 } 6338 6339 PTP_CLI_RESULT_RETURN(CMD_OK); 6340 } else if (parse_cmp("HELP", arg, 0)) { 6341 cli_out(TDPLL_INSTANCE_USAGE_1); 6342 cli_out(TDPLL_INSTANCE_USAGE_2); 6343 } else { 6344 PTP_CLI_RESULT_RETURN(CMD_USAGE); 6345 } 6346 6347 PTP_CLI_RESULT_RETURN(CMD_OK); 6348 } 6349 6350 /* TDPLL INPUTCLK ... */ 6351 /* We divide the string because pedantic compiler doesn't allow strings longer then 509 characters */ 6352 #if defined (BCM_QAX_SUPPORT) 6353 #define TDPLL_INPUTCLK_USAGE_1\ 6354 "TDPLL INputclk <subcommand> [...]\n" \ 6355 "\t TDPLL INputclk [show] [<index>]\n" \ 6356 "\t TDPLL INputclk Get <index>\n" \ 6357 "\t where <index> = | TSGPIO0 | TSGPIO1 | GPIO0 | GPIO1 |\n" \ 6358 "\t | - | - | SyncE1 | SyncE2 |\n" \ 6359 "\t | 1588-Freq | 1588-Phase |\n" \ 6360 "\t TDPLL INputclk Set <index> L1MUX=<mux> L1PORT=<port> MAC=<mac>\n" \ 6361 "\t FREQuency=<value> TSFREQuency=<value> ENable=<y/n>\n" \ 6362 "\t QL=<QL> PRIOrity=<value> LOCKout=<y/n>\n" 6363 #else 6364 #define TDPLL_INPUTCLK_USAGE_1 \ 6365 "TDPLL INputclk <subcommand> [...]\n" \ 6366 "\t TDPLL INputclk [show] [<index>]\n" \ 6367 "\t TDPLL INputclk Get <index>\n" \ 6368 "\t where <index> = | GPIO0 | GPIO1 | GPIO2 | GPIO3 |\n" \ 6369 "\t | GPIO4 | GPIO5 | SyncE1 | SyncE2 |\n" \ 6370 "\t | 1588-Freq | 1588-Phase |\n" \ 6371 "\t TDPLL INputclk Set <index> L1MUX=<mux> L1PORT=<port> MAC=<mac>\n" \ 6372 "\t FREQuency=<value> TSFREQuency=<value> ENable=<y/n>\n" \ 6373 "\t QL=<QL> PRIOrity=<value> LOCKout=<y/n>\n" 6374 #endif 6375 #define TDPLL_INPUTCLK_USAGE_2 \ 6376 "\t where <QL> = | QL-PRC | QL-SSU-A | QL-SSU-B | (Option I)\n" \ 6377 "\t | QL-SEC | QL-DNU | (Option I)\n" \ 6378 "\t | QL-STU | QL-PRS | QL-TNC | (Option II)\n" \ 6379 "\t | QL-ST2 | QL-ST3 | QL-SMC | (Option II)\n" \ 6380 "\t | QL-ST3E | QL-PROV | QL-DUS | (Option II)\n" \ 6381 "\t | QL-UNK | QL-SEC | (Option III)\n" 6382 6383 6384 STATIC cmd_result_t 6385 tdpll_inputclk_show(int unit, int low_idx, int high_idx) 6386 { 6387 int inputclk_idx; 6388 int dpll_idx; 6389 6390 #if !defined(BCM_QAX_SUPPORT) 6391 const char *input_name[TDPLL_INPUT_CLOCK_NUM_MAX] = 6392 {"GPIO0 ","GPIO1 ","GPIO2 ","GPIO3 ","GPIO4 ","GPIO5 ", 6393 "syncE1","syncE2","1588-F", "1588-P"}; 6394 #else 6395 const char *input_name[TDPLL_INPUT_CLOCK_NUM_MAX] = 6396 {"TSGPIO0 ","TSGPIO1 ","GPIO0 ","GPIO1 "," - "," - ", 6397 "syncE1","syncE2","1588-F", "1588-P"}; 6398 #endif 6399 6400 cli_out("ID En? Offset Valid QL Prio LkO Mux DPLLS\n"); 6401 /* add sample & ts frequencies, maybe MAC, on second line? */ 6402 6403 for (inputclk_idx = low_idx; inputclk_idx < high_idx; ++inputclk_idx) { 6404 int freq_error_ppb; 6405 int enabled, dpll_en, best_clock; 6406 bcm_tdpll_input_clock_l1mux_t l1mux; 6407 int valid, soft_warn, hard_accept, hard_reject, priority, lockout; 6408 int dpll_refs[TDPLL_DPLL_INSTANCE_NUM_MAX]; 6409 int num_dplls; 6410 bcm_esmc_quality_level_t ql; 6411 6412 cli_out("%s ", input_name[inputclk_idx]); 6413 6414 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_enable_get( 6415 unit, 0, inputclk_idx, &enabled)); 6416 6417 cli_out(" %c", enabled ? 'Y' : 'N'); 6418 6419 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_frequency_error_get( 6420 unit, 0, inputclk_idx, 6421 &freq_error_ppb)); 6422 6423 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_valid_get( 6424 unit, 0, inputclk_idx, &valid)); 6425 6426 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_threshold_state_get( 6427 unit, 0, inputclk_idx, 6428 bcm_tdpll_input_clock_monitor_type_soft_warn, &soft_warn)); 6429 6430 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_threshold_state_get( 6431 unit, 0, inputclk_idx, 6432 bcm_tdpll_input_clock_monitor_type_hard_accept, &hard_accept)); 6433 6434 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_threshold_state_get( 6435 unit, 0, inputclk_idx, 6436 bcm_tdpll_input_clock_monitor_type_hard_reject, &hard_reject)); 6437 6438 if (!valid && freq_error_ppb == -65249626) { 6439 cli_out(" --- "); 6440 } else { 6441 cli_out("%10d ", freq_error_ppb); 6442 } 6443 6444 if (valid) { 6445 cli_out(" %c ", (soft_warn) ? 'W' : 'Y'); 6446 } else { 6447 cli_out(" %c ", (hard_reject) ? 'R' : 'I'); 6448 } 6449 6450 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_ql_get( 6451 unit, 0, inputclk_idx, &ql)); 6452 6453 cli_out("%8s", 6454 ql == bcm_esmc_g781_I_ql_prc ? "QL-PRC" : 6455 (ql == bcm_esmc_g781_I_ql_ssua ? "QL-SSU-A" : 6456 (ql == bcm_esmc_g781_I_ql_ssub ? "QL-SSU-B" : 6457 (ql == bcm_esmc_g781_I_ql_sec ? "QL-SEC" : 6458 (ql == bcm_esmc_g781_I_ql_dnu ? "QL-DNU" : 6459 (ql == bcm_esmc_g781_II_ql_stu ? "QL-STU" : 6460 (ql == bcm_esmc_g781_II_ql_prs ? "QL-PRS" : 6461 (ql == bcm_esmc_g781_II_ql_tnc ? "QL-TNC" : 6462 (ql == bcm_esmc_g781_II_ql_st2 ? "QL-ST2" : 6463 (ql == bcm_esmc_g781_II_ql_st3 ? "QL-ST3" : 6464 (ql == bcm_esmc_g781_II_ql_smc ? "QL-SMC" : 6465 (ql == bcm_esmc_g781_II_ql_st3e ? "QL-ST3E" : 6466 (ql == bcm_esmc_g781_II_ql_prov ? "QL-PROV" : 6467 (ql == bcm_esmc_g781_II_ql_dus ? "QL-DUS" : 6468 (ql == bcm_esmc_g781_III_ql_unk ? "QL-UNK" : 6469 (ql == bcm_esmc_g781_III_ql_sec ? "QL-SEC" : "Unknown" 6470 )))))))))))))))); 6471 6472 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_priority_get( 6473 unit, 0, inputclk_idx, &priority)); 6474 cli_out("%5d", priority); 6475 6476 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_lockout_get( 6477 unit, 0, inputclk_idx, &lockout)); 6478 cli_out(" %c", lockout ? 'Y' : 'N'); 6479 6480 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_l1mux_get( 6481 unit, 0, inputclk_idx, &l1mux)); 6482 if (l1mux.port >= 0) { 6483 cli_out(" %d.%-2d ", l1mux.index, l1mux.port); 6484 } else { 6485 cli_out(" -- "); 6486 } 6487 6488 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_reference_get( 6489 unit, 0, TDPLL_DPLL_INSTANCE_NUM_MAX, dpll_refs, &num_dplls)); 6490 6491 for (dpll_idx = 0; dpll_idx < TDPLL_DPLL_INSTANCE_NUM_MAX; ++dpll_idx) { 6492 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_dpll_use_get( 6493 unit, 0, inputclk_idx, dpll_idx, &dpll_en)); 6494 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_best_get( 6495 unit, 0, dpll_idx, &best_clock)); 6496 6497 cli_out("%c", 6498 (!dpll_en) ? '-' : /* not on DPLL list of inputs */ 6499 (dpll_refs[dpll_idx] == inputclk_idx) ? '*' : /* Current ref for DPLL */ 6500 (best_clock == inputclk_idx) ? '+' : /* best ref for DPLL, but non-revert */ 6501 (enabled) ? 'x' : /* a backup for the DPLL */ 6502 '.'); /* on DPLL list, not enabled */ 6503 6504 } 6505 cli_out("\n"); 6506 6507 } 6508 6509 return CMD_OK; 6510 } 6511 6512 #if defined(BCM_MONTEREY_SUPPORT) 6513 int get_input_clock_index(int arg_clock_index, int arg_l1mux_port, int arg_l1mux_index) 6514 { 6515 int clock_index = arg_clock_index; 6516 6517 /* "GPIO0", "GPIO1", "GPIO2", "GPIO3", "GPIO4", "GPIO5", "SyncE0", "SyncE1",..., "SyncE64", "1588-Freq", "1588-Phase" */ 6518 if ((clock_index == 6) && (arg_l1mux_port > 0) && (arg_l1mux_port <= 64)) { 6519 /* syncE: 6 -> 69 */ 6520 if (BCM_TDPLL_INPUT_CLOCK_NUM_SYNCE == 2) { 6521 clock_index = clock_index + arg_l1mux_index; 6522 } else { 6523 6524 clock_index = clock_index + (arg_l1mux_port-1); 6525 } 6526 } else if (clock_index == 7) { 6527 /* 1588-Freq:70 */ 6528 clock_index = (BCM_TDPLL_INPUT_CLOCK_NUM_SYNCE + 6); /*70;*/ 6529 } else if (clock_index == 8) { 6530 /* 1588-Phase:71 */ 6531 clock_index = (BCM_TDPLL_INPUT_CLOCK_NUM_SYNCE + 7); /*71;*/ 6532 } else { 6533 cli_out("### get_input_clock_index: Error !! Invalid clock_index or port\n"); 6534 } 6535 cli_out("### get_input_clock_index: ip:clock_index-%d op:clock_index-%d\n", arg_clock_index, clock_index); 6536 6537 return clock_index; 6538 } 6539 6540 int get_output_clock_index(int arg_clock_index, int arg_l1mux_port) 6541 { 6542 int clock_index = arg_clock_index; 6543 6544 /* "BS0", "BS1", "SyncE0", "SyncE1",..., "SyncE63", "1588-Freq", "GPIO_0",...,"GPIO_5" */ 6545 if ((clock_index == 2) && (arg_l1mux_port > 0) && (arg_l1mux_port <= 64)) { 6546 /* syncE: 2 -> 65 */ 6547 clock_index = clock_index + (arg_l1mux_port-1); 6548 } else if (clock_index == 3) { 6549 /* 1588-Freq:66 */ 6550 clock_index = (BCM_TDPLL_OUTPUT_CLOCK_NUM_SYNCE + 2); /*66;*/ 6551 } else if ((clock_index >= 4) && (clock_index <= 9)) { 6552 /* 1588-Phase:67...72 */ 6553 clock_index = (BCM_TDPLL_OUTPUT_CLOCK_NUM_SYNCE + 3) + (clock_index-4); /* 67+(clock_index-4);*/ 6554 } else { 6555 cli_out("### get_output_clock_index: Error !! Invalid clock_index\n"); 6556 } 6557 cli_out("### get_output_clock_index: ip:clock_index-%d op:clock_index-%d\n", arg_clock_index, clock_index); 6558 6559 return clock_index; 6560 } 6561 extern int _bcm_esw_tdpll_outClk_portSet(int unit, int outclock_index, uint32 port); 6562 #endif 6563 6564 6565 #if defined (BCM_MONTEREY_SUPPORT) 6566 int bcm_esw_ptp_map_synce_clock_port(int in_port){ 6567 switch (in_port) { 6568 case 21: 6569 cli_out("Returning 22\n"); 6570 return 22; 6571 case 25: 6572 cli_out("Returning 28\n"); 6573 return 28; 6574 default: 6575 cli_out("Returning %d\n", in_port); 6576 return in_port; 6577 } 6578 } 6579 #endif 6580 6581 STATIC cmd_result_t 6582 cmd_tdpll_inputclk(int unit, args_t *a) 6583 { 6584 parse_table_t pt; 6585 const char *arg = ARG_GET(a); 6586 6587 int invalid_value = 0x7fffffff; 6588 6589 #if defined(BCM_MONTEREY_SUPPORT) 6590 char *arg_index_str[9+1] = 6591 {"GPIO0","GPIO1","GPIO2","GPIO3","GPIO4","GPIO5", 6592 "SyncE","1588-Freq", "1588-Phase", 0}; 6593 #elif !defined(BCM_QAX_SUPPORT) 6594 char *arg_index_str[TDPLL_INPUT_CLOCK_NUM_MAX+1] = 6595 {"GPIO0","GPIO1","GPIO2","GPIO3","GPIO4","GPIO5", 6596 "SyncE1","SyncE2","1588-Freq", "1588-Phase", 0}; 6597 #else 6598 char *arg_index_str[TDPLL_INPUT_CLOCK_NUM_MAX+1] = 6599 {"TSGPIO0","TSGPIO1","GPIO0","GPIO1"," - "," - ", 6600 "SyncE1","SyncE2","1588-Freq", "1588-Phase", 0}; 6601 #endif 6602 int arg_clock_index = -1; /* signal that none was provided */ 6603 int start_index = 0, end_index = TDPLL_INPUT_CLOCK_NUM_MAX; 6604 6605 bcm_tdpll_input_clock_l1mux_t arg_l1mux; 6606 int arg_l1mux_index = 0; 6607 int arg_l1mux_port = 0; 6608 6609 bcm_mac_t arg_mac = {0x00, 0x10, 0x18, 0x00, 0x00, 0x00}; 6610 bcm_mac_t zero_mac = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 6611 6612 int arg_clk_en = 0; 6613 int arg_dpll0_en = 0; 6614 int arg_dpll1_en = 0; 6615 int arg_dpll2_en = 0; 6616 int arg_dpll3_en = 0; 6617 int arg_dpll4_en = 0; 6618 6619 int arg_clock_frequency = 0; 6620 int arg_tsevent_frequency = 4000; 6621 uint32 arg_clock_frequency_rv; 6622 uint32 arg_tsevent_frequency_rv; 6623 int arg_tsevent_quotient_rv = 0; 6624 6625 char *arg_ql_str[16] = {"QL-PRC", "QL-SSU-A", "QL-SSU-B", "QL-SEC", "QL-DNU", 6626 "QL-STU", "QL-PRS", "QL-TNC", "QL-ST2", "QL-ST3", 6627 "QL-SMC", "QL-ST3E", "QL-PROV", "QL-DUS", "QL-UNK", 0}; 6628 6629 int arg_ql_index = invalid_value; 6630 bcm_esmc_quality_level_t arg_ql; 6631 6632 int arg_priority = 0; 6633 int arg_lockout = 0; 6634 int arg_valid = 0; 6635 6636 int arg_over_softwarn = 0; 6637 int arg_under_hardaccept = 0; 6638 int arg_over_hardreject = 0; 6639 6640 int arg_freq_error_ppb = 0; 6641 6642 if (arg) { 6643 char *clock_index_str = ARG_GET(a); 6644 if (clock_index_str) { 6645 arg_clock_index = 0; 6646 while (arg_index_str[arg_clock_index]) { 6647 if (parse_cmp(arg_index_str[arg_clock_index], clock_index_str, 0)) { 6648 break; 6649 } 6650 ++arg_clock_index; 6651 } 6652 if (!arg_index_str[arg_clock_index]) { 6653 cli_out("%s INputclk show/Get/Set: Invalid Clock index '%s'\n", ARG_CMD(a), clock_index_str); 6654 cli_out(TDPLL_INPUTCLK_USAGE_1); 6655 cli_out(TDPLL_INPUTCLK_USAGE_2); 6656 return CMD_FAIL; 6657 } 6658 } 6659 } 6660 6661 if (!arg || parse_cmp("show", arg, 0)) { 6662 if (arg_clock_index >= 0) { 6663 start_index = arg_clock_index; 6664 end_index = arg_clock_index + 1; 6665 } 6666 6667 return tdpll_inputclk_show(unit, start_index, end_index); 6668 } else if (parse_cmp("Get", arg, 0)) { 6669 if (arg_clock_index < 0) { 6670 cli_out("Inputclk index required\n"); 6671 return CMD_USAGE; 6672 } 6673 6674 #if defined(BCM_MONTEREY_SUPPORT) 6675 if (arg_clock_index == 6) { 6676 char *l1Mux = ARG_GET(a); 6677 if (!isint(l1Mux)) { 6678 cli_out("Error!! Invalid port\n"); 6679 return CMD_FAIL; 6680 } 6681 arg_l1mux_index = parse_integer(l1Mux); 6682 if (arg_l1mux_index != 0 && arg_l1mux_index != 1) { 6683 cli_out("Error!! Unsupported syncE\n"); 6684 return CMD_FAIL; 6685 } 6686 } 6687 6688 6689 arg_clock_index = get_input_clock_index(arg_clock_index, 1/*arg_l1mux_index*/, arg_l1mux_index); 6690 #endif 6691 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_l1mux_get( 6692 unit, 0, arg_clock_index, &arg_l1mux)); 6693 6694 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_mac_get( 6695 unit, 0, arg_clock_index, &arg_mac)); 6696 6697 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_enable_get( 6698 unit, 0, arg_clock_index, &arg_clk_en)); 6699 6700 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_dpll_use_get( 6701 unit, 0, arg_clock_index, 0, &arg_dpll0_en)); 6702 6703 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_dpll_use_get( 6704 unit, 0, arg_clock_index, 1, &arg_dpll1_en)); 6705 6706 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_dpll_use_get( 6707 unit, 0, arg_clock_index, 2, &arg_dpll2_en)); 6708 6709 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_dpll_use_get( 6710 unit, PTP_STACK_ID_DEFAULT, arg_clock_index, 3, &arg_dpll3_en)); 6711 6712 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_dpll_use_get( 6713 unit, PTP_STACK_ID_DEFAULT, arg_clock_index, 4, &arg_dpll4_en)); 6714 6715 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_frequency_get( 6716 unit, 0, arg_clock_index, 6717 &arg_clock_frequency_rv, &arg_tsevent_frequency_rv)); 6718 arg_tsevent_quotient_rv = arg_tsevent_frequency_rv ? 6719 (arg_clock_frequency_rv + (arg_tsevent_frequency_rv >> 1))/arg_tsevent_frequency_rv : -1; 6720 6721 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_ql_get( 6722 unit, 0, arg_clock_index, &arg_ql)); 6723 6724 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_priority_get( 6725 unit, 0, arg_clock_index, &arg_priority)); 6726 6727 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_lockout_get( 6728 unit, 0, arg_clock_index, &arg_lockout)); 6729 6730 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_valid_get( 6731 unit, 0, arg_clock_index, &arg_valid)); 6732 6733 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_threshold_state_get( 6734 unit, 0, arg_clock_index, 6735 bcm_tdpll_input_clock_monitor_type_soft_warn, &arg_over_softwarn)); 6736 6737 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_threshold_state_get( 6738 unit, 0, arg_clock_index, 6739 bcm_tdpll_input_clock_monitor_type_hard_accept, &arg_under_hardaccept)); 6740 6741 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_threshold_state_get( 6742 unit, 0, arg_clock_index, 6743 bcm_tdpll_input_clock_monitor_type_hard_reject, &arg_over_hardreject)); 6744 6745 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_frequency_error_get( 6746 unit, 0, arg_clock_index, 6747 &arg_freq_error_ppb)); 6748 6749 cli_out("\n"); 6750 cli_out("T-DPLL Input Clock Data and Metadata.\n"); 6751 cli_out("Unit: %d Stack: %d\n", 6752 unit, 0); 6753 cli_out("-----------------------------------------------------------" 6754 "---------------------\n"); 6755 #if defined(BCM_MONTEREY_SUPPORT) 6756 arg_clock_index = (arg_clock_index == 7)? 6: arg_clock_index; 6757 #endif 6758 cli_out("Index : %d (%s) L1 MUX: %d.%d\n", arg_clock_index, 6759 (arg_clock_index >= 0 && arg_clock_index < TDPLL_INPUT_CLOCK_NUM_MAX) ? 6760 arg_index_str[arg_clock_index] : "Unknown", arg_l1mux.index, arg_l1mux.port); 6761 cli_out("MAC : %02x:%02x:%02x:%02x:%02x:%02x\n", 6762 arg_mac[0], arg_mac[1], arg_mac[2], arg_mac[3], arg_mac[4], arg_mac[5]); 6763 cli_out("\n"); 6764 cli_out("Enable : [%s]\n", arg_clk_en ? "x":" "); 6765 cli_out("\n"); 6766 cli_out("Clock f : %u Hz TS f: %u Hz (Q: %d)\n", (unsigned)arg_clock_frequency_rv, 6767 (unsigned)arg_tsevent_frequency_rv, arg_tsevent_quotient_rv); 6768 cli_out("\n"); 6769 cli_out("QL : %s\n", 6770 arg_ql == bcm_esmc_g781_I_ql_prc ? "QL-PRC" : 6771 (arg_ql == bcm_esmc_g781_I_ql_ssua ? "QL-SSU-A" : 6772 (arg_ql == bcm_esmc_g781_I_ql_ssub ? "QL-SSU-B" : 6773 (arg_ql == bcm_esmc_g781_I_ql_sec ? "QL-SEC" : 6774 (arg_ql == bcm_esmc_g781_I_ql_dnu ? "QL-DNU" : 6775 (arg_ql == bcm_esmc_g781_II_ql_stu ? "QL-STU" : 6776 (arg_ql == bcm_esmc_g781_II_ql_prs ? "QL-PRS" : 6777 (arg_ql == bcm_esmc_g781_II_ql_tnc ? "QL-TNC" : 6778 (arg_ql == bcm_esmc_g781_II_ql_st2 ? "QL-ST2" : 6779 (arg_ql == bcm_esmc_g781_II_ql_st3 ? "QL-ST3" : 6780 (arg_ql == bcm_esmc_g781_II_ql_smc ? "QL-SMC" : 6781 (arg_ql == bcm_esmc_g781_II_ql_st3e ? "QL-ST3E" : 6782 (arg_ql == bcm_esmc_g781_II_ql_prov ? "QL-PROV" : 6783 (arg_ql == bcm_esmc_g781_II_ql_dus ? "QL-DUS" : 6784 (arg_ql == bcm_esmc_g781_III_ql_unk ? "QL-UNK" : 6785 (arg_ql == bcm_esmc_g781_III_ql_sec ? "QL-SEC" : "Unknown" 6786 )))))))))))))))); 6787 cli_out("Priority : %u\n", (unsigned)arg_priority); 6788 cli_out("Lockout : [%s]\n", arg_lockout ? "x":" "); 6789 cli_out("\n"); 6790 cli_out("Valid : [%s]\n", arg_valid ? "x":" "); 6791 cli_out("| Over Soft-Warn [%s] | Under Hard-Accept [%s] | Over Hard-Reject [%s] |\n", 6792 arg_over_softwarn ? "x":" ", arg_under_hardaccept ? "x":" ", arg_over_hardreject ? "x":" "); 6793 cli_out("f Error : %d ppb\n", arg_freq_error_ppb); 6794 cli_out("\n"); 6795 cli_out("DPLLs : | DPLL 0 [%s] | DPLL 1 [%s] | DPLL 2 [%s] | DPLL 3 [%s] | DPLL 4 [%s] |\n", 6796 arg_dpll0_en ? "x":" ", arg_dpll1_en ? "x":" ", 6797 arg_dpll2_en ? "x":" ", arg_dpll3_en ? "x":" ", 6798 arg_dpll4_en ? "x":" "); 6799 cli_out("\n"); 6800 6801 PTP_CLI_RESULT_RETURN(CMD_OK); 6802 6803 } else if (parse_cmp("Set", arg, 0)) { 6804 if (arg_clock_index < 0) { 6805 cli_out("Inputclk index required\n"); 6806 return CMD_USAGE; 6807 } 6808 6809 parse_table_init(unit, &pt); 6810 parse_table_add(&pt, "L1MUX", PQ_INT, (void*)(size_t)invalid_value, 6811 &arg_l1mux_index, NULL); 6812 parse_table_add(&pt, "L1PORT", PQ_INT, (void*)(size_t)invalid_value, 6813 &arg_l1mux_port, NULL); 6814 parse_table_add(&pt, "MAC", PQ_MAC, (void*)0, arg_mac, NULL); 6815 parse_table_add(&pt, "ENable", PQ_BOOL, (void*)(size_t)invalid_value, 6816 &arg_clk_en, NULL); 6817 parse_table_add(&pt, "FREQuency", PQ_INT, (void*)(size_t)invalid_value, 6818 &arg_clock_frequency, NULL); 6819 parse_table_add(&pt, "TSFREQuency", PQ_INT | PQ_DFL, (void*)0, 6820 &arg_tsevent_frequency, NULL); 6821 parse_table_add(&pt, "QL", PQ_MULTI | PQ_DFL, 0, &arg_ql_index, arg_ql_str); 6822 parse_table_add(&pt, "PRIOrity", PQ_INT, (void*)(size_t)invalid_value, 6823 &arg_priority, NULL); 6824 parse_table_add(&pt, "LOCKout", PQ_BOOL, (void*)(size_t)invalid_value, 6825 &arg_lockout, NULL); 6826 6827 if (parse_arg_eq(a, &pt) < 0) { 6828 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 6829 } 6830 parse_arg_eq_done(&pt); 6831 6832 #if defined(BCM_MONTEREY_SUPPORT) 6833 arg_l1mux_port = bcm_esw_ptp_map_synce_clock_port(arg_l1mux_port); 6834 arg_clock_index = get_input_clock_index(arg_clock_index, arg_l1mux_port, arg_l1mux_index); 6835 #endif 6836 6837 if (arg_l1mux_index != invalid_value && arg_l1mux_port != invalid_value) { 6838 arg_l1mux.index = arg_l1mux_index; 6839 arg_l1mux.port = arg_l1mux_port; 6840 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_l1mux_set( 6841 unit, 0, arg_clock_index, &arg_l1mux)); 6842 } 6843 6844 if (sal_memcmp(arg_mac, zero_mac, sizeof(bcm_mac_t))) { 6845 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_mac_set( 6846 unit, 0, arg_clock_index, &arg_mac)); 6847 } 6848 6849 if (arg_clock_frequency != invalid_value) { 6850 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_frequency_set( 6851 unit, 0, 6852 arg_clock_index, (uint32)arg_clock_frequency, (uint32)arg_tsevent_frequency)); 6853 } 6854 6855 if (arg_clk_en != invalid_value) { 6856 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_enable_set( 6857 unit, 0, 6858 arg_clock_index, arg_clk_en)); 6859 } 6860 6861 if (arg_ql_index != invalid_value) { 6862 switch (arg_ql_index) { 6863 case 0: 6864 arg_ql = bcm_esmc_g781_I_ql_prc; 6865 break; 6866 case 1: 6867 arg_ql = bcm_esmc_g781_I_ql_ssua; 6868 break; 6869 case 2: 6870 arg_ql = bcm_esmc_g781_I_ql_ssub; 6871 break; 6872 case 3: 6873 /* NB: Implement support to distinguish Option I/III QL-SEC. */ 6874 arg_ql = bcm_esmc_g781_I_ql_sec; 6875 break; 6876 case 4: 6877 arg_ql = bcm_esmc_g781_I_ql_dnu; 6878 break; 6879 case 5: 6880 arg_ql = bcm_esmc_g781_II_ql_stu; 6881 break; 6882 case 6: 6883 arg_ql = bcm_esmc_g781_II_ql_prs; 6884 break; 6885 case 7: 6886 arg_ql = bcm_esmc_g781_II_ql_tnc; 6887 break; 6888 case 8: 6889 arg_ql = bcm_esmc_g781_II_ql_st2; 6890 break; 6891 case 9: 6892 arg_ql = bcm_esmc_g781_II_ql_st3; 6893 break; 6894 case 10: 6895 arg_ql = bcm_esmc_g781_II_ql_smc; 6896 break; 6897 case 11: 6898 arg_ql = bcm_esmc_g781_II_ql_st3e; 6899 break; 6900 case 12: 6901 arg_ql = bcm_esmc_g781_II_ql_prov; 6902 break; 6903 case 13: 6904 arg_ql = bcm_esmc_g781_II_ql_dus; 6905 break; 6906 case 14: 6907 arg_ql = bcm_esmc_g781_III_ql_unk; 6908 break; 6909 default: 6910 arg_ql = bcm_esmc_ql_unresolvable; 6911 } 6912 6913 if (bcm_esmc_ql_unresolvable == arg_ql) { 6914 cli_out("TDPLL INPUTCLK SET ... : Unresolvable QL.\n"); 6915 } else { 6916 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_ql_set( 6917 unit, 0, arg_clock_index, arg_ql)); 6918 } 6919 } 6920 6921 if (arg_priority != invalid_value) { 6922 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_priority_set( 6923 unit, 0, 6924 arg_clock_index, arg_priority)); 6925 } 6926 6927 if (arg_lockout != invalid_value) { 6928 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_lockout_set( 6929 unit, 0, 6930 arg_clock_index, arg_lockout)); 6931 } 6932 6933 PTP_CLI_RESULT_RETURN(CMD_OK); 6934 6935 } else if (parse_cmp("HELP", arg, 0)) { 6936 cli_out(TDPLL_INPUTCLK_USAGE_1); 6937 cli_out(TDPLL_INPUTCLK_USAGE_2); 6938 } else { 6939 PTP_CLI_RESULT_RETURN(CMD_USAGE); 6940 } 6941 6942 PTP_CLI_RESULT_RETURN(CMD_OK); 6943 } 6944 6945 /* TDPLL OUTPUTCLK ... */ 6946 6947 #if defined (BCM_APACHE_SUPPORT) 6948 #define TDPLL_OUTPUTCLK_USAGE_AP \ 6949 "TDPLL OUTputclk <subcommand> [...]\n" \ 6950 "\t TDPLL OUTputclk Get <index>\n" \ 6951 "\t where <index> = | BroadSync0 | BroadSync1 |\n" \ 6952 "\t | XgPll0 | XgPll1 |\n" \ 6953 "\t | 1588-Hybrid | GPIO0 | GPIO1 |\n" \ 6954 "\t | GPIO2 | GPIO3 | GPIO4 | GPIO5 |\n" \ 6955 "\t | XgPll2 | XgPll3 |\n" \ 6956 "\t TDPLL OUTputclk Set <index> ENable=<y/n>\n" \ 6957 "\t FREQuency=<value> TSFREQuency= <value>\n" \ 6958 "\t DerivFREQuency=<value>\n" 6959 #elif defined (BCM_QAX_SUPPORT) 6960 #define TDPLL_OUTPUTCLK_USAGE_QAX \ 6961 "TDPLL OUTputclk <subcommand> [...]\n" \ 6962 "\t TDPLL OUTputclk Get <index>\n" \ 6963 "\t where <index> = | BroadSync0 | BroadSync1 |\n" \ 6964 "\t | Pml0Pll | Pml1Pll |\n" \ 6965 "\t | 1588-Hybrid | GPIO0 | GPIO1 |\n" \ 6966 "\t | GPIO2 | GPIO3 | - | - | PmhPll\n" \ 6967 "\t TDPLL OUTputclk Set <index> ENable=<y/n>\n" \ 6968 "\t FREQuency=<value> TSFREQuency= <value>\n" \ 6969 "\t DerivFREQuency=<value>\n" 6970 #define TDPLL_OUTPUTCLK_USAGE_QUX \ 6971 "TDPLL OUTputclk <subcommand> [...]\n" \ 6972 "\t TDPLL OUTputclk Get <index>\n" \ 6973 "\t where <index> = | BroadSync0 | BroadSync1 |\n" \ 6974 "\t | PmlPll | PmxPll |\n" \ 6975 "\t | 1588-Hybrid | TSGPIO0 | TSGPIO1 |\n" \ 6976 "\t | GPIO0 | GPIO1 | - | - |\n" \ 6977 "\t TDPLL OUTputclk Set <index> ENable=<y/n>\n" \ 6978 "\t FREQuency=<value> TSFREQuency= <value>\n" \ 6979 "\t DerivFREQuency=<value>\n" 6980 #endif 6981 6982 #if defined (BCM_APACHE_SUPPORT) 6983 #define TDPLL_OUTPUTCLK_USAGE TDPLL_OUTPUTCLK_USAGE_AP 6984 #elif defined (BCM_QAX_SUPPORT) && defined (BCM_QUX_SUPPORT) 6985 #define TDPLL_OUTPUTCLK_USAGE TDPLL_OUTPUTCLK_USAGE_QUX 6986 #elif defined (BCM_QAX_SUPPORT) && !defined (BCM_QUX_SUPPORT) 6987 #define TDPLL_OUTPUTCLK_USAGE TDPLL_OUTPUTCLK_USAGE_QAX 6988 #else 6989 #define TDPLL_OUTPUTCLK_USAGE \ 6990 "TDPLL OUTputclk <subcommand> [...]\n" \ 6991 "\t TDPLL OUTputclk Get <index>\n" \ 6992 "\t where <index> = | BroadSync0 | BroadSync1 |\n" \ 6993 "\t | SerDesLCPLL | MasterLCPLL |\n" \ 6994 "\t | 1588-Hybrid | GPIO0 | GPIO1 |\n" \ 6995 "\t | GPIO2 | GPIO3 | GPIO4 | GPIO5 |\n" \ 6996 "\t TDPLL OUTputclk Set <index> ENable=<y/n>\n" \ 6997 "\t FREQuency=<value> TSFREQuency= <value>\n" \ 6998 "\t DerivFREQuency=<value>\n" 6999 7000 #endif 7001 7002 STATIC cmd_result_t 7003 cmd_tdpll_outputclk(int unit, args_t *a) 7004 { 7005 parse_table_t pt; 7006 const char *arg = ARG_GET(a); 7007 7008 int invalid_value = 0x7fffffff; 7009 7010 char *arg_index_str[TDPLL_OUTPUT_CLOCK_NUM_MAX+1] = 7011 {"BroadSync0", "BroadSync1", "SerDesLCPLL", "MasterLCPLL", "1588-Hybrid", 7012 "GPIO0", "GPIO1", "GPIO2", "GPIO3", "GPIO4", "GPIO5", 0}; 7013 #if defined(BCM_MONTEREY_SUPPORT) 7014 char *arg_index_str_ap[TDPLL_OUTPUT_CLOCK_NUM_MAX+1] = 7015 {"BroadSync0", "BroadSync1", "SyncE1", "SyncE2", "SyncE3", "SyncE4", "1588-Hybrid", 7016 "GPIO0", "GPIO1", "GPIO2", "GPIO3", "GPIO4", "GPIO5", 0}; 7017 #elif defined (BCM_APACHE_SUPPORT) 7018 char *arg_index_str_ap[TDPLL_OUTPUT_CLOCK_NUM_MAX+1] = 7019 {"BroadSync0", "BroadSync1", "XgPll0", "XgPll1", "1588-Hybrid", 7020 "GPIO0", "GPIO1", "GPIO2", "GPIO3", "GPIO4", "GPIO5", "XgPll2", "XgPll3", 0}; 7021 #elif defined (BCM_QAX_SUPPORT) 7022 char *arg_index_str_qax[TDPLL_OUTPUT_CLOCK_NUM_MAX+1] = 7023 {"BroadSync0", "BroadSync1", "Pml0Pll", "Pml1Pll", "1588-Hybrid", 7024 "TSGPIO0", "TSGPIO1", "GPIO0", "GPIO2", " - ", " - ", "PmhPll", 0}; 7025 char *arg_index_str_qux[TDPLL_OUTPUT_CLOCK_NUM_MAX+1] = 7026 {"BroadSync0", "BroadSync1", "PmlPll", "PmxPll", "1588-Hybrid", 7027 "TSGPIO0", "TSGPIO1", "GPIO0", "GPIO2", " - ", " - ", 0}; 7028 #endif 7029 7030 int arg_clock_index = 0; 7031 #if defined(BCM_MONTEREY_SUPPORT) & defined(INCLUDE_GDPLL) 7032 int arg_l1mux_port = 0; 7033 #endif 7034 7035 int arg_clk_en = 0; 7036 7037 int arg_synth_frequency; 7038 int arg_tsevent_frequency = 4000; 7039 int arg_deriv_frequency; 7040 7041 uint32 arg_synth_frequency_rv; 7042 uint32 arg_tsevent_frequency_rv; 7043 uint32 arg_deriv_frequency_rv; 7044 7045 int arg_tsevent_quotient_rv; 7046 int arg_deriv_quotient_rv; 7047 7048 if (arg) { 7049 char *clock_index_str = ARG_GET(a); 7050 #if defined(BCM_MONTEREY_SUPPORT) & defined(INCLUDE_GDPLL) 7051 if (clock_index_str) { 7052 arg_clock_index = 0; 7053 while (arg_index_str_ap[arg_clock_index]) { 7054 if (parse_cmp(arg_index_str_ap[arg_clock_index], clock_index_str, 0)) { 7055 break; 7056 } 7057 ++arg_clock_index; 7058 } 7059 if (!arg_index_str_ap[arg_clock_index]) { 7060 cli_out("%s OUTputclk Get/Set: Invalid Clock index '%s'\n", ARG_CMD(a), clock_index_str); 7061 cli_out(TDPLL_OUTPUTCLK_USAGE_AP); 7062 return CMD_FAIL; 7063 } 7064 7065 /* SyncE */ 7066 if ((arg_clock_index >= 2) && (arg_clock_index <= 5)) { 7067 char *pPort = ARG_GET(a); 7068 if (!isint(pPort)) { 7069 cli_out("### Invalid port\n"); 7070 return CMD_FAIL; 7071 } 7072 arg_l1mux_port = bcm_esw_ptp_map_synce_clock_port(parse_integer(pPort)); 7073 } 7074 /* arg_clock_index = get_output_clock_index(arg_clock_index, arg_l1mux_port); */ 7075 cli_out("### output clock index:%d\n", arg_clock_index); 7076 } 7077 #elif defined (BCM_APACHE_SUPPORT) 7078 if (clock_index_str && SOC_IS_APACHE(unit)) { 7079 arg_clock_index = 0; 7080 while (arg_index_str_ap[arg_clock_index]) { 7081 if (parse_cmp(arg_index_str_ap[arg_clock_index], clock_index_str, 0)) { 7082 break; 7083 } 7084 ++arg_clock_index; 7085 } 7086 if (!arg_index_str_ap[arg_clock_index]) { 7087 cli_out("%s OUTputclk Get/Set: Invalid Clock index '%s'\n", ARG_CMD(a), clock_index_str); 7088 cli_out(TDPLL_OUTPUTCLK_USAGE_AP); 7089 return CMD_FAIL; 7090 } 7091 } else if (clock_index_str) { 7092 arg_clock_index = 0; 7093 while (arg_index_str[arg_clock_index]) { 7094 if (parse_cmp(arg_index_str[arg_clock_index], clock_index_str, 0)) { 7095 break; 7096 } 7097 ++arg_clock_index; 7098 } 7099 if (!arg_index_str[arg_clock_index]) { 7100 cli_out("%s OUTputclk Get/Set: Invalid Clock index '%s'\n", ARG_CMD(a), clock_index_str); 7101 cli_out(TDPLL_OUTPUTCLK_USAGE); 7102 return CMD_FAIL; 7103 } 7104 } 7105 #elif defined (BCM_QAX_SUPPORT) 7106 if (clock_index_str && SOC_IS_QUX(unit)) { 7107 arg_clock_index = 0; 7108 while (arg_index_str_qux[arg_clock_index]) { 7109 if (parse_cmp(arg_index_str_qux[arg_clock_index], clock_index_str, 0)) { 7110 break; 7111 } 7112 ++arg_clock_index; 7113 } 7114 if (!arg_index_str_qux[arg_clock_index]) { 7115 cli_out("%s OUTputclk Get/Set: Invalid Clock index '%s'\n", ARG_CMD(a), clock_index_str); 7116 cli_out(TDPLL_OUTPUTCLK_USAGE_QUX); 7117 return CMD_FAIL; 7118 } 7119 } else if (clock_index_str && SOC_IS_QAX(unit)) { 7120 arg_clock_index = 0; 7121 while (arg_index_str_qax[arg_clock_index]) { 7122 if (parse_cmp(arg_index_str_qax[arg_clock_index], clock_index_str, 0)) { 7123 break; 7124 } 7125 ++arg_clock_index; 7126 } 7127 if (!arg_index_str_qax[arg_clock_index]) { 7128 cli_out("%s OUTputclk Get/Set: Invalid Clock index '%s'\n", ARG_CMD(a), clock_index_str); 7129 cli_out(TDPLL_OUTPUTCLK_USAGE_QAX); 7130 return CMD_FAIL; 7131 } 7132 } else if (clock_index_str) { 7133 arg_clock_index = 0; 7134 while (arg_index_str[arg_clock_index]) { 7135 if (parse_cmp(arg_index_str[arg_clock_index], clock_index_str, 0)) { 7136 break; 7137 } 7138 ++arg_clock_index; 7139 } 7140 if (!arg_index_str[arg_clock_index]) { 7141 cli_out("%s OUTputclk Get/Set: Invalid Clock index '%s'\n", ARG_CMD(a), clock_index_str); 7142 cli_out(TDPLL_OUTPUTCLK_USAGE); 7143 return CMD_FAIL; 7144 } 7145 } 7146 7147 #else 7148 if (clock_index_str) { 7149 arg_clock_index = 0; 7150 while (arg_index_str[arg_clock_index]) { 7151 if (parse_cmp(arg_index_str[arg_clock_index], clock_index_str, 0)) { 7152 break; 7153 } 7154 ++arg_clock_index; 7155 } 7156 if (!arg_index_str[arg_clock_index]) { 7157 cli_out("%s OUTputclk Get/Set: Invalid Clock index '%s'\n", ARG_CMD(a), clock_index_str); 7158 cli_out(TDPLL_OUTPUTCLK_USAGE); 7159 return CMD_FAIL; 7160 } 7161 } 7162 #endif 7163 } 7164 7165 if (!arg) { 7166 PTP_CLI_RESULT_RETURN(CMD_USAGE); 7167 } else if (parse_cmp("Get", arg, 0)) { 7168 PTP_IF_ERROR_RETURN(bcm_tdpll_output_clock_enable_get( 7169 unit, 0, arg_clock_index, &arg_clk_en)); 7170 7171 PTP_IF_ERROR_RETURN(bcm_tdpll_output_clock_synth_frequency_get( 7172 unit, 0, arg_clock_index, 7173 &arg_synth_frequency_rv, &arg_tsevent_frequency_rv)); 7174 arg_tsevent_quotient_rv = arg_tsevent_frequency_rv ? 7175 (arg_synth_frequency_rv + (arg_tsevent_frequency_rv >> 1))/arg_tsevent_frequency_rv : -1; 7176 7177 PTP_IF_ERROR_RETURN(bcm_tdpll_output_clock_deriv_frequency_get( 7178 unit, 0, arg_clock_index, 7179 &arg_deriv_frequency_rv)); 7180 arg_deriv_quotient_rv = arg_deriv_frequency_rv ? 7181 (arg_synth_frequency_rv + (arg_deriv_frequency_rv >> 1))/arg_deriv_frequency_rv : -1; 7182 7183 cli_out("\n"); 7184 cli_out("T-DPLL Output Clock Data and Metadata.\n"); 7185 cli_out("Unit: %d Stack: %d\n", 7186 unit, 0); 7187 cli_out("-----------------------------------------------------------" 7188 "---------------------\n"); 7189 #if defined (BCM_APACHE_SUPPORT) 7190 if (SOC_IS_APACHE(unit)) { 7191 cli_out("Index : %d (%s)\n", arg_clock_index, 7192 /* coverity[check_after_sink : FALSE] */ 7193 (arg_clock_index >= 0 && arg_clock_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) ? 7194 arg_index_str_ap[arg_clock_index] : "Unknown"); 7195 } else { 7196 cli_out("Index : %d (%s)\n", arg_clock_index, 7197 /* coverity[check_after_sink : FALSE] */ 7198 (arg_clock_index >= 0 && arg_clock_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) ? 7199 arg_index_str[arg_clock_index] : "Unknown"); 7200 } 7201 #elif defined (BCM_QAX_SUPPORT) 7202 if (SOC_IS_QUX(unit)) { 7203 cli_out("Index : %d (%s)\n", arg_clock_index, 7204 (arg_clock_index >= 0 && arg_clock_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) ? 7205 arg_index_str_qux[arg_clock_index] : "Unknown"); 7206 } else if (SOC_IS_QAX(unit)) { 7207 cli_out("Index : %d (%s)\n", arg_clock_index, 7208 (arg_clock_index >= 0 && arg_clock_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) ? 7209 arg_index_str_qax[arg_clock_index] : "Unknown"); 7210 }else { 7211 cli_out("Index : %d (%s)\n", arg_clock_index, 7212 (arg_clock_index >= 0 && arg_clock_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) ? 7213 arg_index_str[arg_clock_index] : "Unknown"); 7214 } 7215 #else 7216 cli_out("Index : %d (%s)\n", arg_clock_index, 7217 (arg_clock_index >= 0 && arg_clock_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) ? 7218 arg_index_str[arg_clock_index] : "Unknown"); 7219 #endif 7220 cli_out("\n"); 7221 cli_out("Enable : [%s]\n", arg_clk_en ? "x":" "); 7222 cli_out("\n"); 7223 cli_out("Synth f : %u Hz TS f: %u Hz (Q: %d)\n", (unsigned)arg_synth_frequency_rv, 7224 (unsigned)arg_tsevent_frequency_rv, arg_tsevent_quotient_rv); 7225 cli_out("Deriv f : %u Hz (Q: %d)\n", 7226 (unsigned)arg_deriv_frequency_rv, arg_deriv_quotient_rv); 7227 cli_out("\n"); 7228 7229 PTP_CLI_RESULT_RETURN(CMD_OK); 7230 7231 } else if (parse_cmp("Set", arg, 0)) { 7232 parse_table_init(unit, &pt); 7233 parse_table_add(&pt, "ENable", PQ_BOOL, (void*)(size_t)invalid_value, 7234 &arg_clk_en, NULL); 7235 parse_table_add(&pt, "FREQuency", PQ_INT, (void*)(size_t)invalid_value, 7236 &arg_synth_frequency, NULL); 7237 parse_table_add(&pt, "TSFREQuency", PQ_INT | PQ_DFL, (void*)0, 7238 &arg_tsevent_frequency, NULL); 7239 parse_table_add(&pt, "DerivFREQuency", PQ_INT, (void*)(size_t)invalid_value, 7240 &arg_deriv_frequency, NULL); 7241 7242 if (parse_arg_eq(a, &pt) < 0) { 7243 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 7244 } 7245 parse_arg_eq_done(&pt); 7246 7247 if (arg_synth_frequency != invalid_value) { 7248 PTP_IF_ERROR_RETURN(bcm_tdpll_output_clock_synth_frequency_set( 7249 unit, 0, arg_clock_index, 7250 (uint32)arg_synth_frequency, (uint32)arg_tsevent_frequency)); 7251 } 7252 7253 #if defined(BCM_MONTEREY_SUPPORT) & defined(INCLUDE_GDPLL) 7254 if ((arg_clock_index >= 2) && 7255 (arg_clock_index < (BCM_TDPLL_OUTPUT_CLOCK_NUM_BROADSYNC + BCM_TDPLL_OUTPUT_CLOCK_NUM_SYNCE))) { 7256 /* Output clock is port */ 7257 if (arg_l1mux_port > 0 && arg_l1mux_port <= 64) { 7258 PTP_IF_ERROR_RETURN(_bcm_esw_tdpll_outClk_portSet( 7259 unit, arg_clock_index, arg_l1mux_port)); 7260 } else { 7261 cli_out("Error! Invalid port number\n"); 7262 return CMD_FAIL; 7263 } 7264 } 7265 #endif 7266 if (arg_clk_en != invalid_value) { 7267 PTP_IF_ERROR_RETURN(bcm_tdpll_output_clock_enable_set( 7268 unit, 0, arg_clock_index, arg_clk_en)); 7269 } 7270 7271 if (arg_deriv_frequency != invalid_value) { 7272 PTP_IF_ERROR_RETURN(bcm_tdpll_output_clock_deriv_frequency_set( 7273 unit, 0, arg_clock_index, 7274 (uint32)arg_deriv_frequency)); 7275 } 7276 7277 PTP_CLI_RESULT_RETURN(CMD_OK); 7278 7279 } else if (parse_cmp("HELP", arg, 0)) { 7280 #if defined (BCM_APACHE_SUPPORT) 7281 if (SOC_IS_APACHE(unit)) { 7282 cli_out(TDPLL_OUTPUTCLK_USAGE_AP); 7283 } else { 7284 cli_out(TDPLL_OUTPUTCLK_USAGE); 7285 } 7286 #elif defined (BCM_QAX_SUPPORT) 7287 if (SOC_IS_QUX(unit)) { 7288 cli_out(TDPLL_OUTPUTCLK_USAGE_QUX); 7289 } else if (SOC_IS_QAX(unit)) { 7290 cli_out(TDPLL_OUTPUTCLK_USAGE_QAX); 7291 }else { 7292 cli_out(TDPLL_OUTPUTCLK_USAGE); 7293 } 7294 #else 7295 cli_out(TDPLL_OUTPUTCLK_USAGE); 7296 #endif 7297 } else { 7298 PTP_CLI_RESULT_RETURN(CMD_USAGE); 7299 } 7300 7301 PTP_CLI_RESULT_RETURN(CMD_OK); 7302 } 7303 7304 /* TDPLL MONITOR ... */ 7305 #define TDPLL_MONITOR_USAGE \ 7306 "TDPLL MONitor <subcommand> [...]\n" \ 7307 "\t TDPLL MONitor ConTRoL CallBackENable=<y/n>\n" \ 7308 "\t TDPLL MONitor Get\n" \ 7309 "\t TDPLL MONitor Set INTERVAL=<value-sec>\n" \ 7310 "\t SoFTWaRN=<value-ppb>\n" \ 7311 "\t HaRDACCept=<value-ppb> HaRDREJect=<value-ppb>\n" 7312 7313 STATIC cmd_result_t 7314 cmd_tdpll_monitor(int unit, args_t *a) 7315 { 7316 parse_table_t pt; 7317 const char *arg = ARG_GET(a); 7318 7319 int arg_callback_en; 7320 7321 int invalid_value = 0x7fffffff; 7322 int arg_monitor_interval = 0; 7323 int arg_softwarn_ppb = 0; 7324 int arg_hardaccept_ppb = 0; 7325 int arg_hardreject_ppb = 0; 7326 7327 uint32 arg_monitor_interval_rv; 7328 uint32 arg_softwarn_ppb_rv; 7329 uint32 arg_hardaccept_ppb_rv; 7330 uint32 arg_hardreject_ppb_rv; 7331 7332 if (!arg) { 7333 PTP_CLI_RESULT_RETURN(CMD_USAGE); 7334 } else if (parse_cmp("ConTRoL", arg, 0)) { 7335 parse_table_init(unit, &pt); 7336 parse_table_add(&pt, "CallBackENable", PQ_BOOL, (void*)0, &arg_callback_en, NULL); 7337 7338 if (parse_arg_eq(a, &pt) < 0) { 7339 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 7340 } 7341 parse_arg_eq_done(&pt); 7342 7343 if (arg_callback_en) { 7344 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_monitor_callback_register( 7345 unit, 0, diag_tdpll_input_clock_monitor_callback)); 7346 cli_out("Registering diag_tdpll_input_clock_callback for type bcmTdpllCallbackTypeMonitor\n"); 7347 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_callback_register( 7348 unit, 0, bcmTdpllCallbackTypeMonitor, diag_tdpll_input_clock_callback)); 7349 } else { 7350 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_monitor_callback_unregister( 7351 unit, 0)); 7352 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_callback_unregister( 7353 unit, 0, bcmTdpllCallbackTypeMonitor)); 7354 } 7355 7356 PTP_CLI_RESULT_RETURN(CMD_OK); 7357 7358 } else if (parse_cmp("Get", arg, 0)) { 7359 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_monitor_interval_get( 7360 unit, 0, &arg_monitor_interval_rv)); 7361 7362 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_monitor_threshold_get( 7363 unit, 0, 7364 bcm_tdpll_input_clock_monitor_type_soft_warn, &arg_softwarn_ppb_rv)); 7365 7366 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_monitor_threshold_get( 7367 unit, 0, 7368 bcm_tdpll_input_clock_monitor_type_hard_accept, &arg_hardaccept_ppb_rv)); 7369 7370 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_monitor_threshold_get( 7371 unit, 0, 7372 bcm_tdpll_input_clock_monitor_type_hard_reject, &arg_hardreject_ppb_rv)); 7373 7374 cli_out("\n"); 7375 cli_out("T-DPLL Input Clock Monitoring Parameters and Thresholds.\n"); 7376 cli_out("Unit: %d Stack: %d\n", 7377 unit, PTP_STACK_ID_DEFAULT); 7378 cli_out("-----------------------------------------------------------" 7379 "---------------------\n"); 7380 cli_out("Interval : %u sec\n", (unsigned)arg_monitor_interval_rv); 7381 cli_out("Soft-Warn : %u ppb\n", (unsigned)arg_softwarn_ppb_rv); 7382 cli_out("Hard-Accept: %u ppb\n", (unsigned)arg_hardaccept_ppb_rv); 7383 cli_out("Hard-Reject: %u ppb\n", (unsigned)arg_hardreject_ppb_rv); 7384 cli_out("\n"); 7385 7386 PTP_CLI_RESULT_RETURN(CMD_OK); 7387 7388 } else if (parse_cmp("Set", arg, 0)) { 7389 parse_table_init(unit, &pt); 7390 parse_table_add(&pt, "INTERVAL", PQ_INT, (void*)(size_t)invalid_value, &arg_monitor_interval, NULL); 7391 parse_table_add(&pt, "SoFTWaRN", PQ_INT, (void*)(size_t)invalid_value, &arg_softwarn_ppb, NULL); 7392 parse_table_add(&pt, "HaRDACCept", PQ_INT, (void*)(size_t)invalid_value, &arg_hardaccept_ppb, NULL); 7393 parse_table_add(&pt, "HaRDREJect", PQ_INT, (void*)(size_t)invalid_value, &arg_hardreject_ppb, NULL); 7394 7395 if (parse_arg_eq(a, &pt) < 0) { 7396 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 7397 } 7398 parse_arg_eq_done(&pt); 7399 7400 if (arg_monitor_interval != invalid_value) { 7401 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_monitor_interval_set( 7402 unit, 0, (uint32)arg_monitor_interval)); 7403 } 7404 if (arg_softwarn_ppb != invalid_value) { 7405 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_monitor_threshold_set( 7406 unit, 0, 7407 bcm_tdpll_input_clock_monitor_type_soft_warn, (uint32)arg_softwarn_ppb)); 7408 } 7409 if (arg_hardaccept_ppb != invalid_value) { 7410 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_monitor_threshold_set( 7411 unit, 0, 7412 bcm_tdpll_input_clock_monitor_type_hard_accept, (uint32)arg_hardaccept_ppb)); 7413 } 7414 if (arg_hardreject_ppb != invalid_value) { 7415 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_monitor_threshold_set( 7416 unit, 0, 7417 bcm_tdpll_input_clock_monitor_type_hard_reject, (uint32)arg_hardreject_ppb)); 7418 } 7419 7420 PTP_CLI_RESULT_RETURN(CMD_OK); 7421 7422 } else if (parse_cmp("HELP", arg, 0)) { 7423 cli_out(TDPLL_MONITOR_USAGE); 7424 } else { 7425 PTP_CLI_RESULT_RETURN(CMD_USAGE); 7426 } 7427 7428 PTP_CLI_RESULT_RETURN(CMD_OK); 7429 } 7430 7431 /* TDPLL SELECT ... */ 7432 #define TDPLL_SELECT_USAGE \ 7433 "TDPLL SELect <subcommand> [...]\n" \ 7434 "\t TDPLL SELect ConTRoL CallBackENable=<y/n>\n" \ 7435 "\t TDPLL SELect Get <dpll_index>\n" \ 7436 "\t TDPLL SELect Set <dpll_index> QLENabled=<y/n>\n" 7437 7438 STATIC cmd_result_t 7439 cmd_tdpll_select(int unit, args_t *a) 7440 { 7441 parse_table_t pt; 7442 const char *arg = ARG_GET(a); 7443 7444 int arg_callback_en; 7445 7446 int invalid_value = 0x7fffffff; 7447 7448 char *dpll_index_str; 7449 int arg_dpll_index = 0; 7450 7451 char *arg_reference_str[TDPLL_INPUT_CLOCK_NUM_MAX+1] = 7452 {"GPIO0","GPIO1","GPIO2","GPIO3","GPIO4","GPIO5", 7453 "SyncE1","SyncE2","1588-Freq", "1588-Phase", 0}; 7454 7455 int arg_ql_enabled = 0; 7456 int arg_best_clock = 0; 7457 7458 if (!arg) { 7459 PTP_CLI_RESULT_RETURN(CMD_USAGE); 7460 } else if (parse_cmp("ConTRoL", arg, 0)) { 7461 parse_table_init(unit, &pt); 7462 parse_table_add(&pt, "CallBackENable", PQ_BOOL, (void*)0, &arg_callback_en, NULL); 7463 7464 if (parse_arg_eq(a, &pt) < 0) { 7465 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 7466 } 7467 parse_arg_eq_done(&pt); 7468 7469 if (arg_callback_en) { 7470 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_selector_callback_register( 7471 unit, 0, diag_tdpll_input_clock_selector_callback)); 7472 cli_out("Registering diag_tdpll_input_clock_callback for type bcmTdpllCallbackTypeSelector \n"); 7473 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_callback_register( 7474 unit, 0, bcmTdpllCallbackTypeSelector, diag_tdpll_input_clock_callback)); 7475 } else { 7476 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_selector_callback_unregister( 7477 unit, 0)); 7478 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_callback_unregister( 7479 unit, 0, bcmTdpllCallbackTypeSelector)); 7480 } 7481 7482 PTP_CLI_RESULT_RETURN(CMD_OK); 7483 7484 } 7485 7486 dpll_index_str = ARG_GET(a); 7487 if (dpll_index_str) { 7488 if (!isint(dpll_index_str)) { 7489 cli_out("%s SELect Get/Set: Invalid DPLL index '%s'\n", ARG_CMD(a), dpll_index_str); 7490 cli_out(TDPLL_SELECT_USAGE); 7491 return CMD_FAIL; 7492 } 7493 arg_dpll_index = parse_integer(dpll_index_str); 7494 } 7495 7496 if (parse_cmp("Get", arg, 0)) { 7497 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_ql_enabled_get( 7498 unit, 0, 7499 arg_dpll_index, &arg_ql_enabled)); 7500 7501 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_best_get( 7502 unit, 0, 7503 arg_dpll_index, &arg_best_clock)); 7504 7505 cli_out("\n"); 7506 cli_out("T-DPLL Reference Selection Configuration and State Data.\n"); 7507 cli_out("Unit: %d Stack: %d\n", 7508 unit, 0); 7509 cli_out("-----------------------------------------------------------" 7510 "---------------------\n"); 7511 cli_out("DPLL : %d\n", arg_dpll_index); 7512 cli_out("Modes : QL-Enabled [%s]\n", arg_ql_enabled ? "x":" "); 7513 cli_out("Best : %d (%s)\n", arg_best_clock, 7514 (arg_best_clock >= 0 && arg_best_clock < TDPLL_INPUT_CLOCK_NUM_MAX) ? 7515 arg_reference_str[arg_best_clock] : "Unknown"); 7516 cli_out("\n"); 7517 7518 PTP_CLI_RESULT_RETURN(CMD_OK); 7519 7520 } else if (parse_cmp("Set", arg, 0)) { 7521 parse_table_init(unit, &pt); 7522 parse_table_add(&pt, "QLENabled", PQ_BOOL, (void*)(size_t)invalid_value, &arg_ql_enabled, NULL); 7523 7524 if (parse_arg_eq(a, &pt) < 0) { 7525 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 7526 } 7527 parse_arg_eq_done(&pt); 7528 7529 if (arg_ql_enabled != invalid_value) { 7530 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_ql_enabled_set( 7531 unit, 0, 7532 arg_dpll_index, arg_ql_enabled)); 7533 } 7534 7535 PTP_CLI_RESULT_RETURN(CMD_OK); 7536 7537 } else if (parse_cmp("HELP", arg, 0)) { 7538 cli_out(TDPLL_SELECT_USAGE); 7539 } else { 7540 PTP_CLI_RESULT_RETURN(CMD_USAGE); 7541 } 7542 7543 PTP_CLI_RESULT_RETURN(CMD_OK); 7544 } 7545 7546 /* TDPLL SELECT ... */ 7547 #define TDPLL_NOTIFICATION_USAGE \ 7548 "TDPLL NOTIfication ConTRoL CallBackENable=<y/n>\n" 7549 7550 STATIC cmd_result_t 7551 cmd_tdpll_notification(int unit, args_t *a) 7552 { 7553 parse_table_t pt; 7554 const char *arg = ARG_GET(a); 7555 7556 int arg_callback_en; 7557 7558 if (!arg) { 7559 PTP_CLI_RESULT_RETURN(CMD_USAGE); 7560 } else if (parse_cmp("ConTRoL", arg, 0)) { 7561 parse_table_init(unit, &pt); 7562 parse_table_add(&pt, "CallBackENable", PQ_BOOL, (void*)0, &arg_callback_en, NULL); 7563 7564 if (parse_arg_eq(a, &pt) < 0) { 7565 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 7566 } 7567 parse_arg_eq_done(&pt); 7568 7569 if (arg_callback_en) { 7570 cli_out("Registering diag_tdpll_input_clock_callback for type bcmTdpllCallbackTypeNotification \n"); 7571 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_callback_register( 7572 unit, 0, bcmTdpllCallbackTypeNotification, diag_tdpll_input_clock_callback)); 7573 } else { 7574 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_callback_unregister( 7575 unit, 0, bcmTdpllCallbackTypeNotification)); 7576 } 7577 7578 PTP_CLI_RESULT_RETURN(CMD_OK); 7579 7580 } 7581 7582 PTP_CLI_RESULT_RETURN(CMD_OK); 7583 } 7584 /* TDPLL SWITCH ... */ 7585 #define TDPLL_SWITCH_USAGE \ 7586 "TDPLL SWitch <subcommand> [...]\n" \ 7587 "\t TDPLL SWitch ConTRoL ENable=<y/n>\n" \ 7588 "\t TDPLL SWitch Get <dpll_index>\n" \ 7589 "\t TDPLL SWitch Set <dpll_index> REVertive=<y/n>\n" 7590 7591 STATIC cmd_result_t 7592 cmd_tdpll_switch(int unit, args_t *a) 7593 { 7594 parse_table_t pt; 7595 const char *arg = ARG_GET(a); 7596 7597 int invalid_value = 0x7fffffff; 7598 int arg_dpc_en = 0; 7599 7600 char *dpll_index_str; 7601 int arg_dpll_index = 0; 7602 7603 char *arg_reference_str[TDPLL_INPUT_CLOCK_NUM_MAX] = 7604 {"GPIO0","GPIO1","GPIO2","GPIO3","GPIO4","GPIO5", 7605 "SyncE1","SyncE2","1588-Freq","1588-Phase"}; 7606 7607 int arg_revertive = 0; 7608 7609 int arg_best_clock = 0; 7610 int arg_dpll_ref[TDPLL_DPLL_INSTANCE_NUM_MAX]; 7611 int arg_num_dpll; 7612 7613 if (!arg) { 7614 PTP_CLI_RESULT_RETURN(CMD_USAGE); 7615 } else if (parse_cmp("ConTRoL", arg, 0)) { 7616 parse_table_init(unit, &pt); 7617 parse_table_add(&pt, "ENable", PQ_BOOL, (void*)(size_t)invalid_value, &arg_dpc_en, NULL); 7618 7619 if (parse_arg_eq(a, &pt) < 0) { 7620 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 7621 } 7622 parse_arg_eq_done(&pt); 7623 7624 if (invalid_value != arg_dpc_en) { 7625 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_control(unit, 0, arg_dpc_en)); 7626 } 7627 PTP_CLI_RESULT_RETURN(CMD_OK); 7628 7629 } 7630 7631 dpll_index_str = ARG_GET(a); 7632 if (dpll_index_str) { 7633 if (!isint(dpll_index_str)) { 7634 cli_out("%s SWitch Get/Set: Invalid DPLL index '%s'\n", ARG_CMD(a), dpll_index_str); 7635 cli_out(TDPLL_SWITCH_USAGE); 7636 return CMD_FAIL; 7637 } 7638 arg_dpll_index = parse_integer(dpll_index_str); 7639 } 7640 7641 if (parse_cmp("Get", arg, 0)) { 7642 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_revertive_get( 7643 unit, 0, 7644 arg_dpll_index, &arg_revertive)); 7645 7646 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_best_get( 7647 unit, 0, 7648 arg_dpll_index, &arg_best_clock)); 7649 7650 PTP_IF_ERROR_RETURN(bcm_tdpll_dpll_reference_get( 7651 unit, 0, 7652 TDPLL_DPLL_INSTANCE_NUM_MAX, arg_dpll_ref, &arg_num_dpll)); 7653 7654 cli_out("\n"); 7655 cli_out("T-DPLL Reference Switching Configuration and State Data.\n"); 7656 cli_out("Unit: %d Stack: %d\n", 7657 unit, 0); 7658 cli_out("-----------------------------------------------------------" 7659 "---------------------\n"); 7660 cli_out("DPLL : %d\n", arg_dpll_index); 7661 cli_out("Modes : | Revertive [%s] |\n", 7662 arg_revertive ? "x":" "); 7663 cli_out("Ref. : %d %s (%d %s)\n", 7664 (arg_dpll_index >= 0 && arg_dpll_index < TDPLL_DPLL_INSTANCE_NUM_MAX) ? 7665 arg_dpll_ref[arg_dpll_index] : -1, 7666 (arg_dpll_index >= 0 && arg_dpll_index < TDPLL_DPLL_INSTANCE_NUM_MAX) && 7667 (arg_dpll_ref[arg_dpll_index] >= 0) && 7668 (arg_dpll_ref[arg_dpll_index] < TDPLL_INPUT_CLOCK_NUM_MAX) ? 7669 arg_reference_str[arg_dpll_ref[arg_dpll_index]] : "Unknown", 7670 arg_best_clock, 7671 (arg_dpll_index >= 0 && arg_dpll_index < TDPLL_DPLL_INSTANCE_NUM_MAX) && 7672 (arg_best_clock >= 0) && 7673 (arg_best_clock < TDPLL_INPUT_CLOCK_NUM_MAX) ? 7674 arg_reference_str[arg_best_clock] : "Unknown"); 7675 cli_out("\n"); 7676 7677 PTP_CLI_RESULT_RETURN(CMD_OK); 7678 7679 } else if (parse_cmp("Set", arg, 0)) { 7680 parse_table_init(unit, &pt); 7681 parse_table_add(&pt, "REVertive", PQ_BOOL, (void*)(size_t)invalid_value, &arg_revertive, NULL); 7682 7683 if (parse_arg_eq(a, &pt) < 0) { 7684 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 7685 } 7686 parse_arg_eq_done(&pt); 7687 7688 if (arg_revertive != invalid_value) { 7689 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_revertive_set( 7690 unit, 0, 7691 arg_dpll_index, arg_revertive)); 7692 } 7693 7694 PTP_CLI_RESULT_RETURN(CMD_OK); 7695 7696 } else if (parse_cmp("HELP", arg, 0)) { 7697 cli_out(TDPLL_SWITCH_USAGE); 7698 } else { 7699 PTP_CLI_RESULT_RETURN(CMD_USAGE); 7700 } 7701 7702 PTP_CLI_RESULT_RETURN(CMD_OK); 7703 } 7704 7705 /* TDPLL HOLDOVER ... */ 7706 /* We divide the string because pedantic compiler doesn't allow strings longer then 509 characters */ 7707 #define TDPLL_HOLDOVER_USAGE_1_AP \ 7708 "TDPLL HOLDover <subcommand> [...]\n" \ 7709 "\t TDPLL HOLDover Get <output>\n" \ 7710 "\t where <output> = | BroadSync0 | BroadSync1 |\n" \ 7711 "\t | XgPll0 | XgPll1 |\n" \ 7712 "\t | 1588-Hybrid | XgPll2 | XgPll3 \n" 7713 #define TDPLL_HOLDOVER_USAGE_1_QAX \ 7714 "TDPLL HOLDover <subcommand> [...]\n" \ 7715 "\t TDPLL HOLDover Get <output>\n" \ 7716 "\t where <output> = | BroadSync0 | BroadSync1 |\n" \ 7717 "\t | Pml0Pll | Pml1Pll |\n" \ 7718 "\t | 1588-Hybrid | PmhPll \n" 7719 #define TDPLL_HOLDOVER_USAGE_1_QUX \ 7720 "TDPLL HOLDover <subcommand> [...]\n" \ 7721 "\t TDPLL HOLDover Get <output>\n" \ 7722 "\t where <output> = | BroadSync0 | BroadSync1 |\n" \ 7723 "\t | PmlPll | PmxPll |\n" \ 7724 "\t | 1588-Hybrid \n" 7725 7726 #define TDPLL_HOLDOVER_USAGE_2 \ 7727 "\t TDPLL HOLDover Set <ouput> [FREQuency=<freqppt>] [Mode=<mode>]\n" \ 7728 "\t where <mode> = | INSTantaneous | ONEsecond | MANual |\n" \ 7729 "\t | FASTaverage | SLOWaverage |\n" \ 7730 "\t TDPLL HOLDover RESET <output>\n" 7731 7732 #if defined (BCM_APACHE_SUPPORT) 7733 #define TDPLL_HOLDOVER_USAGE_1 TDPLL_HOLDOVER_USAGE_1_AP 7734 #elif defined (BCM_QAX_SUPPORT) && defined (BCM_QUX_SUPPORT) 7735 #define TDPLL_HOLDOVER_USAGE_1 TDPLL_HOLDOVER_USAGE_1_QUX 7736 #elif defined (BCM_QAX_SUPPORT) && !defined (BCM_QUX_SUPPORT) 7737 #define TDPLL_HOLDOVER_USAGE_1 TDPLL_HOLDOVER_USAGE_1_QAX 7738 #else 7739 #define TDPLL_HOLDOVER_USAGE_1 \ 7740 "TDPLL HOLDover <subcommand> [...]\n" \ 7741 "\t TDPLL HOLDover Get <output>\n" \ 7742 "\t where <output> = | BroadSync0 | BroadSync1 |\n" \ 7743 "\t | SerDesLCPLL | MasterLCPLL |\n" \ 7744 "\t | 1588-Hybrid | \n" 7745 #endif 7746 7747 STATIC cmd_result_t 7748 cmd_tdpll_holdover(int unit, args_t *a) 7749 { 7750 parse_table_t pt; 7751 const char *arg = ARG_GET(a); 7752 7753 bcm_tdpll_holdover_data_t arg_hdata; 7754 bcm_tdpll_holdover_mode_t arg_hmode = bcm_tdpll_holdover_mode_slow_average; 7755 7756 char *arg_index_str[TDPLL_OUTPUT_CLOCK_NUM_MAX+1] = 7757 {"BroadSync0", "BroadSync1", "SerDesLCPLL", "MasterLCPLL", "1588-Hybrid", 0}; 7758 #if defined(BCM_APACHE_SUPPORT) 7759 /* Initializing with dummy string for GPIO clocks to retain same indices for XGPLL2/3 */ 7760 char *arg_index_str_ap[TDPLL_OUTPUT_CLOCK_NUM_MAX+1] = 7761 {"BroadSync0", "BroadSync1", "XgPll0", "XgPll1", "1588-Hybrid", "dummy1", "dummy2", 7762 "dummy3", "dummy4", "dummy5", "dummy6","XgPll2", "XgPll3", 0}; 7763 #elif defined(BCM_QAX_SUPPORT) 7764 char *arg_index_str_qux[TDPLL_OUTPUT_CLOCK_NUM_MAX+1] = 7765 {"BroadSync0", "BroadSync1", "PmlPll", "PmxPll", "1588-Hybrid", "dummy1", "dummy2", 7766 "dummy3", "dummy4", "dummy5", "dummy6", 0}; 7767 char *arg_index_str_qax[TDPLL_OUTPUT_CLOCK_NUM_MAX+1] = 7768 {"BroadSync0", "BroadSync1", "Pml0Pll", "Pml1Pll", "1588-Hybrid", "dummy1", "dummy2", 7769 "dummy3", "dummy4", "dummy5", "dummy6","PmhPll", 0}; 7770 7771 #endif 7772 int arg_index = 0; 7773 int arg_freqppt; 7774 7775 int invalid_value = 0x7fffffff; 7776 char *arg_mode_str[6] = {"INSTantaneous", "ONEsecond", "MANual", "FASTaverage", "SLOWaverage", 0}; 7777 7778 if (arg) { 7779 char *clock_index_str = ARG_GET(a); 7780 #if defined (BCM_APACHE_SUPPORT) 7781 if (clock_index_str && SOC_IS_APACHE(unit)) { 7782 arg_index = 0; 7783 while (arg_index_str_ap[arg_index]) { 7784 if (parse_cmp(arg_index_str_ap[arg_index], clock_index_str, 0)) { 7785 break; 7786 } 7787 ++arg_index; 7788 } 7789 if (!arg_index_str_ap[arg_index]) { 7790 cli_out("%s HOLDover Get/Set: Invalid Output '%s'\n", ARG_CMD(a), clock_index_str); 7791 cli_out(TDPLL_HOLDOVER_USAGE_1_AP); 7792 cli_out(TDPLL_HOLDOVER_USAGE_2); 7793 return CMD_FAIL; 7794 } 7795 } else 7796 #elif defined (BCM_QAX_SUPPORT) 7797 if (clock_index_str && SOC_IS_QUX(unit)) { 7798 arg_index = 0; 7799 while (arg_index_str_qux[arg_index]) { 7800 if (parse_cmp(arg_index_str_qux[arg_index], clock_index_str, 0)) { 7801 break; 7802 } 7803 ++arg_index; 7804 } 7805 if (!arg_index_str_qux[arg_index]) { 7806 cli_out("%s HOLDover Get/Set: Invalid Output '%s'\n", ARG_CMD(a), clock_index_str); 7807 cli_out(TDPLL_HOLDOVER_USAGE_1_QUX); 7808 cli_out(TDPLL_HOLDOVER_USAGE_2); 7809 return CMD_FAIL; 7810 } 7811 } else if (clock_index_str && SOC_IS_QAX(unit)) { 7812 arg_index = 0; 7813 while (arg_index_str_qax[arg_index]) { 7814 if (parse_cmp(arg_index_str_qax[arg_index], clock_index_str, 0)) { 7815 break; 7816 } 7817 ++arg_index; 7818 } 7819 if (!arg_index_str_qax[arg_index]) { 7820 cli_out("%s HOLDover Get/Set: Invalid Output '%s'\n", ARG_CMD(a), clock_index_str); 7821 cli_out(TDPLL_HOLDOVER_USAGE_1_QAX); 7822 cli_out(TDPLL_HOLDOVER_USAGE_2); 7823 return CMD_FAIL; 7824 } 7825 } else 7826 7827 #endif 7828 if (clock_index_str) { 7829 arg_index = 0; 7830 while (arg_index_str[arg_index]) { 7831 if (parse_cmp(arg_index_str[arg_index], clock_index_str, 0)) { 7832 break; 7833 } 7834 ++arg_index; 7835 } 7836 if (!arg_index_str[arg_index]) { 7837 cli_out("%s HOLDover Get/Set: Invalid Output '%s'\n", ARG_CMD(a), clock_index_str); 7838 cli_out(TDPLL_HOLDOVER_USAGE_1); 7839 cli_out(TDPLL_HOLDOVER_USAGE_2); 7840 return CMD_FAIL; 7841 } 7842 } 7843 } 7844 7845 if (!arg) { 7846 PTP_CLI_RESULT_RETURN(CMD_USAGE); 7847 } else if (parse_cmp("Get", arg, 0)) { 7848 PTP_IF_ERROR_RETURN(bcm_tdpll_output_clock_holdover_data_get(unit, 0, 7849 arg_index, &arg_hdata)); 7850 7851 cli_out("\n"); 7852 cli_out("T-DPLL Holdover State and Configuration Data.\n"); 7853 cli_out("Unit: %d Stack: %d\n", 7854 unit, 0); 7855 cli_out("-----------------------------------------------------------" 7856 "---------------------\n"); 7857 #if defined (BCM_APACHE_SUPPORT) 7858 if (SOC_IS_APACHE(unit)) { 7859 cli_out("Index : %d (%s)\n", arg_index, 7860 /* coverity[check_after_sink : FALSE] */ 7861 (arg_index >= 0 && arg_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) ? 7862 arg_index_str_ap[arg_index] : "Unknown"); 7863 } else { 7864 cli_out("Index : %d (%s)\n", arg_index, 7865 /* coverity[check_after_sink : FALSE] */ 7866 (arg_index >= 0 && arg_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) ? 7867 arg_index_str[arg_index] : "Unknown"); 7868 } 7869 #elif defined (BCM_QAX_SUPPORT) 7870 if (SOC_IS_QUX(unit)) { 7871 cli_out("Index : %d (%s)\n", arg_index, 7872 (arg_index >= 0 && arg_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) ? 7873 arg_index_str_qux[arg_index] : "Unknown"); 7874 } else if (SOC_IS_QAX(unit)) { 7875 cli_out("Index : %d (%s)\n", arg_index, 7876 (arg_index >= 0 && arg_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) ? 7877 arg_index_str_qax[arg_index] : "Unknown"); 7878 } else { 7879 cli_out("Index : %d (%s)\n", arg_index, 7880 (arg_index >= 0 && arg_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) ? 7881 arg_index_str[arg_index] : "Unknown"); 7882 } 7883 7884 #else 7885 cli_out("Index : %d (%s)\n", arg_index, 7886 (arg_index >= 0 && arg_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) ? 7887 arg_index_str[arg_index] : "Unknown"); 7888 #endif 7889 cli_out("Mode : | [%s] Instantaneous | [%s] 1sec | [%s] Manual | [%s] Fast-Avg | [%s] Slow-Avg |\n", 7890 arg_hdata.mode == bcm_tdpll_holdover_mode_instantaneous ? "x" : " ", 7891 arg_hdata.mode == bcm_tdpll_holdover_mode_avg1s ? "x" : " ", 7892 arg_hdata.mode == bcm_tdpll_holdover_mode_manual ? "x" : " ", 7893 arg_hdata.mode == bcm_tdpll_holdover_mode_fast_average ? "x" : " ", 7894 arg_hdata.mode == bcm_tdpll_holdover_mode_slow_average ? "x" : " "); 7895 cli_out("f (Instantaneous): %d ppt\n", arg_hdata.freq_instantaneous); 7896 cli_out("f (1sec Average) : %d ppt\n", arg_hdata.freq_avg1s); 7897 cli_out("f (Manual) : %d ppt\n", arg_hdata.freq_manual); 7898 cli_out("f (Fast Average) : %d ppt [%s] Valid\n", arg_hdata.freq_fast_average, 7899 arg_hdata.freq_fast_average_valid ? "x" : " "); 7900 cli_out("f (Slow Average) : %d ppt [%s] Valid\n", arg_hdata.freq_slow_average, 7901 arg_hdata.freq_slow_average_valid ? "x" : " "); 7902 cli_out("\n"); 7903 7904 PTP_CLI_RESULT_RETURN(CMD_OK); 7905 7906 } else if (parse_cmp("Set", arg, 0)) { 7907 parse_table_init(unit, &pt); 7908 parse_table_add(&pt, "FREQuency", PQ_INT, (void*)(size_t)invalid_value, &arg_freqppt, NULL); 7909 parse_table_add(&pt, "Mode", PQ_MULTI | PQ_DFL, 0, &arg_hmode, arg_mode_str); 7910 7911 if (parse_arg_eq(a, &pt) < 0) { 7912 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 7913 } 7914 parse_arg_eq_done(&pt); 7915 7916 PTP_IF_ERROR_RETURN(bcm_tdpll_output_clock_holdover_mode_set(unit, 0, arg_index, arg_hmode)); 7917 7918 if (arg_freqppt != invalid_value) { 7919 PTP_IF_ERROR_RETURN(bcm_tdpll_output_clock_holdover_frequency_set(unit, 0, arg_index, arg_freqppt)); 7920 } 7921 7922 PTP_CLI_RESULT_RETURN(CMD_OK); 7923 7924 } else if (parse_cmp("RESET", arg, 0)) { 7925 parse_table_init(unit, &pt); 7926 parse_table_add(&pt, "INDeX", PQ_MULTI | PQ_DFL, 0, &arg_index, &arg_index_str); 7927 7928 if (parse_arg_eq(a, &pt) < 0) { 7929 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 7930 } 7931 parse_arg_eq_done(&pt); 7932 7933 PTP_IF_ERROR_RETURN(bcm_tdpll_output_clock_holdover_reset(unit, 0, arg_index)); 7934 PTP_CLI_RESULT_RETURN(CMD_OK); 7935 7936 } else if (parse_cmp("HELP", arg, 0)) { 7937 #if defined (BCM_APACHE_SUPPORT) 7938 if (SOC_IS_APACHE(unit)) { 7939 cli_out(TDPLL_HOLDOVER_USAGE_1_AP); 7940 } 7941 else { 7942 cli_out(TDPLL_HOLDOVER_USAGE_1); 7943 } 7944 #elif defined (BCM_QAX_SUPPORT) 7945 if (SOC_IS_QUX(unit)) { 7946 cli_out(TDPLL_HOLDOVER_USAGE_1_QUX); 7947 } else if (SOC_IS_QAX(unit)) { 7948 cli_out(TDPLL_HOLDOVER_USAGE_1_QAX); 7949 } else { 7950 cli_out(TDPLL_HOLDOVER_USAGE_1); 7951 } 7952 #else 7953 cli_out(TDPLL_HOLDOVER_USAGE_1); 7954 #endif 7955 cli_out(TDPLL_HOLDOVER_USAGE_2); 7956 } else { 7957 PTP_CLI_RESULT_RETURN(CMD_USAGE); 7958 } 7959 7960 PTP_CLI_RESULT_RETURN(CMD_OK); 7961 } 7962 7963 7964 /* TDPLL ESMC ... */ 7965 /* We divide the string because pedantic compiler doesn't allow strings longer then 509 characters */ 7966 #define TDPLL_ESMC_USAGE_1 \ 7967 "TDPLL ESMC <subcommand> [...]\n" \ 7968 "\t TDPLL ESMC Get <dpll_index>\n" \ 7969 "\t TDPLL ESMC Set <dpll_index> MAC=<mac> QL=<QL>\n" \ 7970 "\t HoldoverQL=<QL> G781=<OPTionI|OPTionII|OPTionIII>\n" \ 7971 "\t RXENable=<y/n> TXENable=<y/n>\n" \ 7972 "\t RXPortBitMaP=<port bitmap> TXPortBitMaP=<port bitmap>\n" \ 7973 "\t G8264ESSMCode=<essm_code>\n" \ 7974 "\t TDPLL ESMC Register <dpll_index> G8273PhaseTransientEnable=<y/n>\n" \ 7975 "\t where <QL> = | QL-PRC | QL-SSU-A | QL-SSU-B | (Option I)\n" 7976 #define TDPLL_ESMC_USAGE_2 \ 7977 "\t | QL-SEC | QL-DNU | (Option I)\n" \ 7978 "\t | QL-STU | QL-PRS | QL-TNC | (Option II)\n" \ 7979 "\t | QL-ST2 | QL-ST3 | QL-SMC | (Option II)\n" \ 7980 "\t | QL-ST3E | QL-PROV | QL-DUS | (Option II)\n" \ 7981 "\t | QL-UNK | QL-SEC | (Option III)\n" \ 7982 "\t NOTE: G781 and RXENable are global attributes, which apply\n" \ 7983 "\t to all T-DPLL instances.\n" 7984 #define TDPLL_ESMC_USAGE_3 \ 7985 "\t where <essm_code> = \n" \ 7986 "\t <0 - bcmEsmcEssmCodeNone> | <0xff - bcmEsmcEssmCodeEEC>\n" 7987 7988 STATIC cmd_result_t 7989 cmd_tdpll_esmc(int unit, args_t *a) 7990 { 7991 parse_table_t pt; 7992 const char *arg = ARG_GET(a); 7993 7994 int invalid_value = 0x7fffffff; 7995 7996 char *dpll_index_str; 7997 int arg_dpll_index = 0; 7998 int arg_rx_enable = invalid_value; 7999 int arg_tx_enable = invalid_value; 8000 8001 char *arg_rx_pbmp_str = 0; 8002 char *arg_tx_pbmp_str = 0; 8003 bcm_pbmp_t arg_rx_pbmp; 8004 bcm_pbmp_t arg_tx_pbmp; 8005 8006 char *rxbufp = NULL; 8007 char *txbufp = NULL; 8008 int rxbufp_len; 8009 int txbufp_len; 8010 8011 int rxrv; 8012 int txrv; 8013 8014 bcm_mac_t arg_mac = {0x00, 0x10, 0x18, 0x00, 0x00, 0x00}; 8015 bcm_mac_t zero_mac = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 8016 8017 char *arg_g781_str[4] = {"OPTionI", "OPTionII", "OPTionIII", 0}; 8018 int arg_g781_index = invalid_value; 8019 bcm_esmc_network_option_t arg_g781_option; 8020 8021 char *arg_ql_str[16] = {"QL-PRC", "QL-SSU-A", "QL-SSU-B", "QL-SEC", "QL-DNU", 8022 "QL-STU", "QL-PRS", "QL-TNC", "QL-ST2", "QL-ST3", 8023 "QL-SMC", "QL-ST3E", "QL-PROV", "QL-DUS", "QL-UNK", 0}; 8024 8025 int arg_ql_index = invalid_value; 8026 int arg_holdover_ql_index = invalid_value; 8027 8028 bcm_esmc_quality_level_t arg_ql; 8029 bcm_esmc_quality_level_t arg_holdover_ql; 8030 int g8273_phase_transient_enable = 0; 8031 bcm_esmc_essm_code_t essm_code = bcmEsmcEssmCodeNone; 8032 8033 dpll_index_str = ARG_GET(a); 8034 if (dpll_index_str) { 8035 if (!isint(dpll_index_str)) { 8036 cli_out("%s ESMC Get/Set: Invalid DPLL index '%s'\n", ARG_CMD(a), dpll_index_str); 8037 cli_out(TDPLL_ESMC_USAGE_1); 8038 cli_out(TDPLL_ESMC_USAGE_2); 8039 cli_out(TDPLL_ESMC_USAGE_3); 8040 return CMD_FAIL; 8041 } 8042 arg_dpll_index = parse_integer(dpll_index_str); 8043 } 8044 8045 if (!arg) { 8046 PTP_CLI_RESULT_RETURN(CMD_USAGE); 8047 } else if (parse_cmp("Get", arg, 0)) { 8048 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_mac_get( 8049 unit, 0, arg_dpll_index, &arg_mac)); 8050 8051 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_ql_get( 8052 unit, 0, arg_dpll_index, &arg_ql)); 8053 8054 #ifndef BCM_ESMC_EXTDPLL_SUPPORT 8055 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_holdover_ql_get( 8056 unit, 0, arg_dpll_index, &arg_holdover_ql)); 8057 #endif /* BCM_ESMC_EXTDPLL_SUPPORT */ 8058 8059 PTP_IF_ERROR_RETURN(bcm_esmc_g781_option_get( 8060 unit, 0, &arg_g781_option)); 8061 8062 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_rx_enable_get( 8063 unit, 0, &arg_rx_enable)); 8064 8065 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_tx_enable_get( 8066 unit, 0, arg_dpll_index, &arg_tx_enable)); 8067 8068 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_rx_portbitmap_get( 8069 unit, 0, arg_dpll_index, &arg_rx_pbmp)); 8070 8071 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_tx_portbitmap_get( 8072 unit, 0, arg_dpll_index, &arg_tx_pbmp)); 8073 8074 rxbufp_len = FORMAT_PBMP_MAX * sizeof(*rxbufp); 8075 rxbufp = sal_alloc(rxbufp_len, "Rx ESMC portbitmap print buffer"); 8076 if (NULL == rxbufp) { 8077 PTP_CLI_RESULT_RETURN(CMD_FAIL); 8078 } 8079 format_bcm_pbmp(unit, rxbufp, rxbufp_len, arg_rx_pbmp); 8080 8081 txbufp_len = FORMAT_PBMP_MAX * sizeof(*txbufp); 8082 txbufp = sal_alloc(txbufp_len, "Tx ESMC portbitmap print buffer"); 8083 if (NULL == txbufp) { 8084 sal_free(rxbufp); 8085 PTP_CLI_RESULT_RETURN(CMD_FAIL); 8086 } 8087 format_bcm_pbmp(unit, txbufp, txbufp_len, arg_tx_pbmp); 8088 8089 cli_out("\n"); 8090 cli_out("T-DPLL Ethernet Synchronization Messaging Channel (ESMC).\n"); 8091 cli_out("Unit: %d Stack: %d\n", 8092 unit, 0); 8093 cli_out("-----------------------------------------------------------" 8094 "---------------------\n"); 8095 cli_out("DPLL : %d\n", arg_dpll_index); 8096 cli_out("MAC : %02x:%02x:%02x:%02x:%02x:%02x\n", 8097 arg_mac[0], arg_mac[1], arg_mac[2], arg_mac[3], arg_mac[4], arg_mac[5]); 8098 cli_out("\n"); 8099 8100 cli_out("QL : %s\n", 8101 arg_ql == bcm_esmc_g781_I_ql_prc ? "QL-PRC" : 8102 (arg_ql == bcm_esmc_g781_I_ql_ssua ? "QL-SSU-A" : 8103 (arg_ql == bcm_esmc_g781_I_ql_ssub ? "QL-SSU-B" : 8104 (arg_ql == bcm_esmc_g781_I_ql_sec ? "QL-SEC" : 8105 (arg_ql == bcm_esmc_g781_I_ql_dnu ? "QL-DNU" : 8106 (arg_ql == bcm_esmc_g781_II_ql_stu ? "QL-STU" : 8107 (arg_ql == bcm_esmc_g781_II_ql_prs ? "QL-PRS" : 8108 (arg_ql == bcm_esmc_g781_II_ql_tnc ? "QL-TNC" : 8109 (arg_ql == bcm_esmc_g781_II_ql_st2 ? "QL-ST2" : 8110 (arg_ql == bcm_esmc_g781_II_ql_st3 ? "QL-ST3" : 8111 (arg_ql == bcm_esmc_g781_II_ql_smc ? "QL-SMC" : 8112 (arg_ql == bcm_esmc_g781_II_ql_st3e ? "QL-ST3E" : 8113 (arg_ql == bcm_esmc_g781_II_ql_prov ? "QL-PROV" : 8114 (arg_ql == bcm_esmc_g781_II_ql_dus ? "QL-DUS" : 8115 (arg_ql == bcm_esmc_g781_III_ql_unk ? "QL-UNK" : 8116 (arg_ql == bcm_esmc_g781_III_ql_sec ? "QL-SEC" : "Unknown" 8117 )))))))))))))))); 8118 8119 #ifndef BCM_ESMC_EXTDPLL_SUPPORT 8120 cli_out("Holdover QL : %s\n", 8121 arg_holdover_ql == bcm_esmc_g781_I_ql_prc ? "QL-PRC" : 8122 (arg_holdover_ql == bcm_esmc_g781_I_ql_ssua ? "QL-SSU-A" : 8123 (arg_holdover_ql == bcm_esmc_g781_I_ql_ssub ? "QL-SSU-B" : 8124 (arg_holdover_ql == bcm_esmc_g781_I_ql_sec ? "QL-SEC" : 8125 (arg_holdover_ql == bcm_esmc_g781_I_ql_dnu ? "QL-DNU" : 8126 (arg_holdover_ql == bcm_esmc_g781_II_ql_stu ? "QL-STU" : 8127 (arg_holdover_ql == bcm_esmc_g781_II_ql_prs ? "QL-PRS" : 8128 (arg_holdover_ql == bcm_esmc_g781_II_ql_tnc ? "QL-TNC" : 8129 (arg_holdover_ql == bcm_esmc_g781_II_ql_st2 ? "QL-ST2" : 8130 (arg_holdover_ql == bcm_esmc_g781_II_ql_st3 ? "QL-ST3" : 8131 (arg_holdover_ql == bcm_esmc_g781_II_ql_smc ? "QL-SMC" : 8132 (arg_holdover_ql == bcm_esmc_g781_II_ql_st3e ? "QL-ST3E" : 8133 (arg_holdover_ql == bcm_esmc_g781_II_ql_prov ? "QL-PROV" : 8134 (arg_holdover_ql == bcm_esmc_g781_II_ql_dus ? "QL-DUS" : 8135 (arg_holdover_ql == bcm_esmc_g781_III_ql_unk ? "QL-UNK" : 8136 (arg_holdover_ql == bcm_esmc_g781_III_ql_sec ? "QL-SEC" : "Unknown" 8137 )))))))))))))))); 8138 #endif /* BCM_ESMC_EXTDPLL_SUPPORT */ 8139 8140 cli_out("ITU-T G.781 : %s (%d)\n", 8141 arg_g781_option == bcm_esmc_network_option_g781_I ? "Option I" : 8142 (arg_g781_option == bcm_esmc_network_option_g781_II ? "Option II" : 8143 (arg_g781_option == bcm_esmc_network_option_g781_III ? "Option III" : "Unknown")), 8144 (int)arg_g781_option); 8145 cli_out("\n"); 8146 8147 cli_out("Rx Enable : [%s] (%s)\n", arg_rx_enable ? "x":" ", rxbufp); 8148 cli_out("Tx Enable : [%s] (%s)\n", arg_tx_enable ? "x":" ", txbufp); 8149 8150 cli_out("\n"); 8151 8152 bcm_tdpll_esmc_essm_code_get( unit, 0, arg_dpll_index, &essm_code); 8153 cli_out("G.8264 ESSM code : "); 8154 8155 switch(essm_code) { 8156 case bcmEsmcEssmCodeNone: 8157 cli_out("bcmEsmcEssmCodeNone\n"); 8158 break; 8159 case bcmEsmcEssmCodeEEC: 8160 cli_out("bcmEsmcEssmCodeEEC\n"); 8161 break; 8162 case bcmEsmcEssmCodePRTC: 8163 cli_out("bcmEsmcEssmCodePRTC\n"); 8164 break; 8165 case bcmEsmcEssmCodeEPRTC: 8166 cli_out("bcmEsmcEssmCodeEPRTC\n"); 8167 break; 8168 case bcmEsmcEssmCodeEEEC: 8169 cli_out("bcmEsmcEssmCodeEEEC\n"); 8170 break; 8171 } 8172 8173 sal_free(rxbufp); 8174 sal_free(txbufp); 8175 PTP_CLI_RESULT_RETURN(CMD_OK); 8176 8177 } else if (parse_cmp("Set", arg, 0)) { 8178 parse_table_init(unit, &pt); 8179 parse_table_add(&pt, "MAC", PQ_MAC, (void*)0, arg_mac, NULL); 8180 parse_table_add(&pt, "QL", PQ_MULTI | PQ_DFL, 0, &arg_ql_index, arg_ql_str); 8181 parse_table_add(&pt, "HoldoverQL", PQ_MULTI | PQ_DFL, 0, &arg_holdover_ql_index, arg_ql_str); 8182 parse_table_add(&pt, "G781", PQ_MULTI | PQ_DFL, 0, &arg_g781_index, arg_g781_str); 8183 parse_table_add(&pt, "RXENable", PQ_BOOL, (void*)(size_t)invalid_value, &arg_rx_enable, NULL); 8184 parse_table_add(&pt, "TXENable", PQ_BOOL, (void*)(size_t)invalid_value, &arg_tx_enable, NULL); 8185 parse_table_add(&pt, "RXPortBitMaP", PQ_STRING, (void*)"", &arg_rx_pbmp_str, NULL); 8186 parse_table_add(&pt, "TXPortBitMaP", PQ_STRING, (void*)"", &arg_tx_pbmp_str, NULL); 8187 parse_table_add(&pt, "G8264ESSMCode", PQ_INT, (void*)0, &essm_code, NULL); 8188 8189 if (parse_arg_eq(a, &pt) < 0) { 8190 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 8191 } 8192 8193 8194 rxrv = parse_bcm_pbmp(unit, arg_rx_pbmp_str, &arg_rx_pbmp); 8195 txrv = parse_bcm_pbmp(unit, arg_tx_pbmp_str, &arg_tx_pbmp); 8196 8197 parse_arg_eq_done(&pt); 8198 8199 if (sal_memcmp(arg_mac, zero_mac, sizeof(bcm_mac_t))) { 8200 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_mac_set( 8201 unit, 0, arg_dpll_index, &arg_mac)); 8202 } 8203 8204 if (invalid_value == arg_g781_index) 8205 { 8206 PTP_IF_ERROR_RETURN(bcm_esmc_g781_option_get( 8207 unit, 0, &arg_g781_option)); 8208 } else { 8209 arg_g781_option = (bcm_esmc_network_option_t)(arg_g781_index + 1); 8210 PTP_IF_ERROR_RETURN(bcm_esmc_g781_option_set( 8211 unit, 0, arg_g781_option)); 8212 } 8213 8214 if (invalid_value != arg_ql_index) { 8215 arg_ql = bcm_esmc_ql_unresolvable; 8216 switch (arg_ql_index) { 8217 case 0: 8218 if (bcm_esmc_network_option_g781_I == arg_g781_option) { 8219 arg_ql = bcm_esmc_g781_I_ql_prc; 8220 } 8221 break; 8222 case 1: 8223 if (bcm_esmc_network_option_g781_I == arg_g781_option) { 8224 arg_ql = bcm_esmc_g781_I_ql_ssua; 8225 } 8226 break; 8227 case 2: 8228 if (bcm_esmc_network_option_g781_I == arg_g781_option) { 8229 arg_ql = bcm_esmc_g781_I_ql_ssub; 8230 } 8231 break; 8232 case 3: 8233 if (bcm_esmc_network_option_g781_I == arg_g781_option) { 8234 arg_ql = bcm_esmc_g781_I_ql_sec; 8235 } else if (bcm_esmc_network_option_g781_III == arg_g781_option) { 8236 arg_ql = bcm_esmc_g781_III_ql_sec; 8237 } 8238 break; 8239 case 4: 8240 if (bcm_esmc_network_option_g781_I == arg_g781_option) { 8241 arg_ql = bcm_esmc_g781_I_ql_dnu; 8242 } 8243 break; 8244 case 5: 8245 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8246 arg_ql = bcm_esmc_g781_II_ql_stu; 8247 } 8248 break; 8249 case 6: 8250 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8251 arg_ql = bcm_esmc_g781_II_ql_prs; 8252 } 8253 break; 8254 case 7: 8255 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8256 arg_ql = bcm_esmc_g781_II_ql_tnc; 8257 } 8258 break; 8259 case 8: 8260 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8261 arg_ql = bcm_esmc_g781_II_ql_st2; 8262 } 8263 break; 8264 case 9: 8265 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8266 arg_ql = bcm_esmc_g781_II_ql_st3; 8267 } 8268 break; 8269 case 10: 8270 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8271 arg_ql = bcm_esmc_g781_II_ql_smc; 8272 } 8273 break; 8274 case 11: 8275 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8276 arg_ql = bcm_esmc_g781_II_ql_st3e; 8277 } 8278 break; 8279 case 12: 8280 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8281 arg_ql = bcm_esmc_g781_II_ql_prov; 8282 } 8283 break; 8284 case 13: 8285 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8286 arg_ql = bcm_esmc_g781_II_ql_dus; 8287 } 8288 break; 8289 case 14: 8290 if (bcm_esmc_network_option_g781_III == arg_g781_option) { 8291 arg_ql = bcm_esmc_g781_III_ql_unk; 8292 } 8293 break; 8294 default: 8295 arg_ql = bcm_esmc_ql_unresolvable; 8296 } 8297 8298 if (bcm_esmc_ql_unresolvable == arg_ql) { 8299 cli_out("TDPLL ESMC SET ... : Incompatible QL and ITU-T G.781 networking option.\n"); 8300 } else { 8301 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_ql_set( 8302 unit, 0, arg_dpll_index, arg_ql)); 8303 } 8304 8305 } 8306 8307 if (invalid_value != arg_holdover_ql_index) { 8308 arg_holdover_ql = bcm_esmc_ql_unresolvable; 8309 switch (arg_holdover_ql_index) { 8310 case 0: 8311 if (bcm_esmc_network_option_g781_I == arg_g781_option) { 8312 arg_holdover_ql = bcm_esmc_g781_I_ql_prc; 8313 } 8314 break; 8315 case 1: 8316 if (bcm_esmc_network_option_g781_I == arg_g781_option) { 8317 arg_holdover_ql = bcm_esmc_g781_I_ql_ssua; 8318 } 8319 break; 8320 case 2: 8321 if (bcm_esmc_network_option_g781_I == arg_g781_option) { 8322 arg_holdover_ql = bcm_esmc_g781_I_ql_ssub; 8323 } 8324 break; 8325 case 3: 8326 if (bcm_esmc_network_option_g781_I == arg_g781_option) { 8327 arg_holdover_ql = bcm_esmc_g781_I_ql_sec; 8328 } else if (bcm_esmc_network_option_g781_III == arg_g781_option) { 8329 arg_holdover_ql = bcm_esmc_g781_III_ql_sec; 8330 } 8331 break; 8332 case 4: 8333 if (bcm_esmc_network_option_g781_I == arg_g781_option) { 8334 arg_holdover_ql = bcm_esmc_g781_I_ql_dnu; 8335 } 8336 break; 8337 case 5: 8338 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8339 arg_holdover_ql = bcm_esmc_g781_II_ql_stu; 8340 } 8341 break; 8342 case 6: 8343 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8344 arg_holdover_ql = bcm_esmc_g781_II_ql_prs; 8345 } 8346 break; 8347 case 7: 8348 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8349 arg_holdover_ql = bcm_esmc_g781_II_ql_tnc; 8350 } 8351 break; 8352 case 8: 8353 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8354 arg_holdover_ql = bcm_esmc_g781_II_ql_st2; 8355 } 8356 break; 8357 case 9: 8358 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8359 arg_holdover_ql = bcm_esmc_g781_II_ql_st3; 8360 } 8361 break; 8362 case 10: 8363 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8364 arg_holdover_ql = bcm_esmc_g781_II_ql_smc; 8365 } 8366 break; 8367 case 11: 8368 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8369 arg_holdover_ql = bcm_esmc_g781_II_ql_st3e; 8370 } 8371 break; 8372 case 12: 8373 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8374 arg_holdover_ql = bcm_esmc_g781_II_ql_prov; 8375 } 8376 break; 8377 case 13: 8378 if (bcm_esmc_network_option_g781_II == arg_g781_option) { 8379 arg_holdover_ql = bcm_esmc_g781_II_ql_dus; 8380 } 8381 break; 8382 case 14: 8383 if (bcm_esmc_network_option_g781_III == arg_g781_option) { 8384 arg_holdover_ql = bcm_esmc_g781_III_ql_unk; 8385 } 8386 break; 8387 default: 8388 arg_holdover_ql = bcm_esmc_ql_unresolvable; 8389 } 8390 8391 if (bcm_esmc_ql_unresolvable == arg_holdover_ql) { 8392 cli_out("TDPLL ESMC SET ... : Incompatible Holdover QL and ITU-T G.781 networking option.\n"); 8393 } else { 8394 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_holdover_ql_set( 8395 unit, 0, arg_dpll_index, arg_holdover_ql)); 8396 } 8397 } 8398 8399 if (invalid_value != arg_rx_enable) { 8400 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_rx_enable_set( 8401 unit, 0, arg_rx_enable)); 8402 if (arg_rx_enable) { 8403 #ifdef BCM_ESMC_EXTDPLL_SUPPORT 8404 PTP_IF_ERROR_RETURN(bcm_extdpll_esmc_event_cb_register(unit, 0)); 8405 #else 8406 PTP_IF_ERROR_RETURN(bcm_esmc_rx_callback_register(unit, 0, 8407 bcm_tdpll_esmc_rx_state_machine)); 8408 #endif 8409 } else { 8410 #ifdef BCM_ESMC_EXTDPLL_SUPPORT 8411 PTP_IF_ERROR_RETURN(bcm_extdpll_esmc_event_cb_unregister(unit, 0)); 8412 #else 8413 PTP_IF_ERROR_RETURN(bcm_esmc_rx_callback_unregister(unit, 0)); 8414 #endif 8415 } 8416 } 8417 8418 if (invalid_value != arg_tx_enable) { 8419 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_tx_enable_set( 8420 unit, 0, arg_dpll_index, arg_tx_enable)); 8421 } 8422 8423 if (BCM_SUCCESS(rxrv)) { 8424 /* Valid port bitmap for ESMC Rx. */ 8425 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_rx_portbitmap_set(unit, 0, 8426 arg_dpll_index, arg_rx_pbmp)); 8427 } 8428 8429 if (BCM_SUCCESS(txrv)) { 8430 /* Valid port bitmap for ESMC Tx. */ 8431 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_tx_portbitmap_set(unit, 0, 8432 arg_dpll_index, arg_tx_pbmp)); 8433 } 8434 8435 switch(essm_code) { 8436 case bcmEsmcEssmCodeNone: 8437 case bcmEsmcEssmCodeEEC: 8438 PTP_IF_ERROR_RETURN(bcm_tdpll_esmc_essm_code_set(unit, 0, 8439 arg_dpll_index, essm_code)); 8440 break; 8441 case bcmEsmcEssmCodePRTC: 8442 case bcmEsmcEssmCodeEPRTC: 8443 case bcmEsmcEssmCodeEEEC: 8444 default: 8445 cli_out("Unsupported G.8264 essm code - %02x\n", (unsigned)essm_code); 8446 break; 8447 } 8448 8449 PTP_CLI_RESULT_RETURN(CMD_OK); 8450 } else if (parse_cmp("Register", arg, 0)) { 8451 parse_table_init(unit, &pt); 8452 parse_table_add(&pt, "G8273PhaseTransientEnable", PQ_BOOL, (void*)0, &g8273_phase_transient_enable, NULL); 8453 8454 if (parse_arg_eq(a, &pt) < 0) { 8455 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 8456 } 8457 8458 parse_arg_eq_done(&pt); 8459 8460 if (g8273_phase_transient_enable) { 8461 cli_out("Registering TDPLL phase transient callback..\n"); 8462 PTP_IF_ERROR_RETURN(bcm_tdpll_input_clock_ql_change_callback_register( 8463 unit, 0, diag_tdpll_input_clock_ql_change_callback)); 8464 } else { 8465 cli_out("Un-registering TDPLL phase transient callback..\n"); 8466 bcm_tdpll_input_clock_ql_change_callback_unregister(unit, 0); 8467 } 8468 } else if (parse_cmp("HELP", arg, 0)) { 8469 cli_out(TDPLL_ESMC_USAGE_1); 8470 cli_out(TDPLL_ESMC_USAGE_2); 8471 cli_out(TDPLL_ESMC_USAGE_3); 8472 } else { 8473 PTP_CLI_RESULT_RETURN(CMD_USAGE); 8474 } 8475 8476 PTP_CLI_RESULT_RETURN(CMD_OK); 8477 } 8478 8479 #endif /* __KERNEL__ */ 8480 8481 8482 #define PTP_HELP_USAGE \ 8483 "PTP HELP <subcommand>\n" \ 8484 "\t \"PTP HELP LIST\" prints list of subcommands\n" 8485 8486 STATIC cmd_result_t 8487 cmd_ptp_help(int unit, args_t *a) 8488 { 8489 const char * arg; 8490 subcommand_t *cmd; 8491 8492 arg = ARG_GET(a); 8493 if (arg) { 8494 cmd = subcommands_list; 8495 while (cmd->str) { 8496 if (parse_cmp(cmd->str, arg, 0)) { 8497 if (cmd->help) { 8498 cli_out("%s", cmd->help); 8499 } 8500 if (cmd->help_ext) { 8501 cli_out("%s", cmd->help_ext); 8502 } 8503 PTP_CLI_RESULT_RETURN(CMD_OK); 8504 } 8505 ++cmd; 8506 } 8507 } 8508 8509 /* No valid argument */ 8510 cli_out("PTP HELP <subcommand> with <subcommand> from:\n"); 8511 8512 cmd = subcommands_list; 8513 while (cmd->str) { 8514 const char* first_cmd = (cmd++)->str; 8515 const char* second_cmd = ""; 8516 if (cmd->str) { 8517 second_cmd = (cmd++)->str; 8518 } 8519 cli_out(" %20s%20s\n", first_cmd, second_cmd); 8520 } 8521 8522 PTP_CLI_RESULT_RETURN(CMD_OK); 8523 } 8524 8525 /************************************************************************* 8526 * Main PTP command 8527 */ 8528 8529 char cmd_ptp_usage[] = 8530 #ifdef COMPILER_STRING_CONST_LIMIT 8531 " PTP <option> [args...]\n" 8532 #else /* COMPILER_STRING_CONST_LIMIT */ 8533 " " PTP_STACK_USAGE "\n" 8534 " " PTP_CLOCK_USAGE "\n" 8535 " " PTP_PORT_USAGE "\n" 8536 " " PTP_TIME_USAGE "\n" 8537 " " PTP_CHANNELS_USAGE_1 PTP_CHANNELS_USAGE_2 "\n" 8538 " " PTP_SIGNAL_USAGE "\n" 8539 " " PTP_SYNCPHY_USAGE "\n" 8540 #ifndef __KERNEL__ 8541 " " PTP_TODOUT_USAGE_1 PTP_TODOUT_USAGE_2 "\n" 8542 " " PTP_TODIN_USAGE_1 PTP_TODIN_USAGE_2"\n" 8543 " " PTP_SERVO_USAGE_1 PTP_SERVO_USAGE_2 PTP_SERVO_USAGE_3 "\n" 8544 " " PTP_MASTER_USAGE_1 PTP_MASTER_USAGE_2 "\n" 8545 " " PTP_SLAVE_USAGE "\n" 8546 " " PTP_PEER_DATASET_GET_USAGE "\n" 8547 " " PTP_PACKET_COUNTERS_GET_USAGE "\n" 8548 " " PTP_DEBUG_USAGE "\n" 8549 " " PTP_LOG_USAGE "\n" 8550 " " PTP_REGISTER_USAGE "\n" 8551 " " PTP_TELECOM_USAGE_1 PTP_TELECOM_USAGE_2 "\n" 8552 " " PTP_CTDEV_USAGE "\n" 8553 " " PTP_MODULAR_USAGE "\n" 8554 " " PTP_DIAGSHELL_USAGE "\n" 8555 #endif /* __KERNEL__ */ 8556 " " PTP_HELP_USAGE "\n" 8557 #endif /* COMPILER_STRING_CONST_LIMIT */ 8558 ; 8559 8560 8561 static subcommand_t subcommands[] = { 8562 {"Stack", cmd_ptp_stack, PTP_STACK_USAGE, 0}, 8563 {"Clock", cmd_ptp_clock, PTP_CLOCK_USAGE, 0}, 8564 {"Port", cmd_ptp_port, PTP_PORT_USAGE, 0}, 8565 {"Time", cmd_ptp_time, PTP_TIME_USAGE, 0}, 8566 {"CHannels", cmd_ptp_channels, PTP_CHANNELS_USAGE_1, PTP_CHANNELS_USAGE_2}, 8567 {"SIGnals", cmd_ptp_signals, PTP_SIGNAL_USAGE, 0}, 8568 {"SyncPhy", cmd_ptp_syncphy, PTP_SYNCPHY_USAGE, 0}, 8569 #ifndef __KERNEL__ 8570 {"ToDOut", cmd_ptp_tod_out, PTP_TODOUT_USAGE_1, PTP_TODOUT_USAGE_2}, 8571 {"ToDIn", cmd_ptp_tod_in, PTP_TODIN_USAGE_1, PTP_TODIN_USAGE_2}, 8572 {"SerVO", cmd_ptp_servo, PTP_SERVO_USAGE_1, PTP_SERVO_USAGE_2}, 8573 {"MaSTer", cmd_ptp_master, PTP_MASTER_USAGE_1, PTP_MASTER_USAGE_2}, 8574 {"SLaVe", cmd_ptp_slave, PTP_SLAVE_USAGE, 0}, 8575 {"PeerDataset", cmd_ptp_peer_dataset_get, PTP_PEER_DATASET_GET_USAGE, 0}, 8576 {"CounTeRs", cmd_ptp_packet_counters_get, PTP_PACKET_COUNTERS_GET_USAGE, 0}, 8577 {"DeBug", cmd_ptp_debug, PTP_DEBUG_USAGE, 0}, 8578 {"Log", cmd_ptp_log, PTP_LOG_USAGE, 0}, 8579 {"REGister", cmd_ptp_register, PTP_REGISTER_USAGE, 0}, 8580 {"TELecom", cmd_ptp_telecom, PTP_TELECOM_USAGE_1, PTP_TELECOM_USAGE_2}, 8581 {"CTDEV", cmd_ptp_ctdev, PTP_CTDEV_USAGE, 0}, 8582 {"MODULAR", cmd_ptp_modular, PTP_MODULAR_USAGE, 0}, 8583 {"DIAGshell", cmd_ptp_diagshell, PTP_DIAGSHELL_USAGE, 0}, 8584 {"TsFifo", cmd_ptp_ts_fifo, PTP_TSFIFO_USAGE, 0}, 8585 #endif /* __KERNEL__ */ 8586 {"HELP", cmd_ptp_help, PTP_HELP_USAGE, 0}, 8587 {0, 0, 0, 0} 8588 }; 8589 8590 static subcommand_t *subcommands_list = subcommands; 8591 8592 cmd_result_t 8593 cmd_ptp(int unit, args_t *a) 8594 { 8595 char *arg; 8596 subcommand_t *cmd; 8597 8598 arg = ARG_GET(a); 8599 if (!arg) { 8600 PTP_CLI_RESULT_RETURN(CMD_USAGE); 8601 } 8602 8603 cmd = subcommands; 8604 while (cmd->str) { 8605 if (parse_cmp(cmd->str, arg, 0)) { 8606 /* Peek at next argument. If it is help, we deal with it here */ 8607 if (ARG_CUR(a) && parse_cmp("HELP", ARG_CUR(a), 0)) { 8608 arg = ARG_GET(a); /* peel off the "HELP" to avoid warning */ 8609 8610 /* Help for subcommand */ 8611 if (cmd->help) { 8612 cli_out("%s", cmd->help); 8613 } 8614 if (cmd->help_ext) { 8615 cli_out("%s", cmd->help_ext); 8616 } 8617 PTP_CLI_RESULT_RETURN(CMD_OK); 8618 } else { 8619 /* Execute the subcommand */ 8620 return (*cmd->func)(unit, a); 8621 } 8622 } 8623 ++cmd; 8624 } 8625 8626 PTP_CLI_RESULT_RETURN(CMD_USAGE); 8627 } 8628 8629 /* T-DPLL command gateway. */ 8630 char cmd_tdpll_usage[] = "Usages:\n" 8631 #ifdef COMPILER_STRING_CONST_LIMIT 8632 " TDPLL <option> [args...]\n" 8633 #else /* COMPILER_STRING_CONST_LIMIT */ 8634 #ifndef __KERNEL__ 8635 " " TDPLL_INSTANCE_USAGE_1 TDPLL_INSTANCE_USAGE_2 "\n" 8636 " " TDPLL_INPUTCLK_USAGE_1 TDPLL_INPUTCLK_USAGE_2 "\n" 8637 " " TDPLL_OUTPUTCLK_USAGE "\n" 8638 " " TDPLL_MONITOR_USAGE "\n" 8639 " " TDPLL_SELECT_USAGE "\n" 8640 " " TDPLL_SWITCH_USAGE "\n" 8641 " " TDPLL_HOLDOVER_USAGE_1 TDPLL_HOLDOVER_USAGE_2 "\n" 8642 " " TDPLL_ESMC_USAGE_1 TDPLL_ESMC_USAGE_2 TDPLL_ESMC_USAGE_3"\n" 8643 #endif /* __KERNEL__ */ 8644 #endif /* COMPILER_STRING_CONST_LIMIT */ 8645 ; 8646 8647 cmd_result_t 8648 cmd_tdpll(int unit, args_t *a) 8649 { 8650 subcommand_t subcommands[] = { 8651 #ifndef __KERNEL__ 8652 {"INSTance", cmd_tdpll_instance}, 8653 {"INputclk", cmd_tdpll_inputclk}, 8654 {"OUTputclk", cmd_tdpll_outputclk}, 8655 {"MONitor", cmd_tdpll_monitor}, 8656 {"SELect", cmd_tdpll_select}, 8657 {"NOTIfication", cmd_tdpll_notification}, 8658 {"SWitch", cmd_tdpll_switch}, 8659 {"ESMC", cmd_tdpll_esmc}, 8660 {"HOLDover", cmd_tdpll_holdover}, 8661 #endif /* __KERNEL__ */ 8662 }; 8663 8664 char *arg; 8665 8666 int i; 8667 8668 arg = ARG_GET(a); 8669 if (!arg) { 8670 PTP_CLI_RESULT_RETURN(CMD_USAGE); 8671 } 8672 8673 for (i = 0; i < sizeof(subcommands) / sizeof(subcommands[0]); ++i) { 8674 if (parse_cmp(subcommands[i].str, arg, 0)) { 8675 return (*subcommands[i].func)(unit, a); 8676 } 8677 } 8678 8679 PTP_CLI_RESULT_RETURN(CMD_USAGE); 8680 } 8681 8682 #ifndef __KERNEL__ 8683 8684 /***************************************************************************** 8685 * Minimal ARP handler, for bare-bones use of Diag Shell with no other L3 8686 * framework in place. 8687 */ 8688 8689 #define ARP_IPV4_LEN (28) 8690 #define ARP_REQUEST (1) 8691 #define ARP_RESPONSE (2) 8692 #define OPCODE_OFFSET (6) 8693 #define PROTOCOL_OFFSET (2) 8694 #define SENDER_IPV4_MAC_OFFSET (8) 8695 #define SENDER_IPV4_ADDR_OFFSET (14) 8696 #define TARGET_IPV4_MAC_OFFSET (18) 8697 #define TARGET_IPV4_ADDR_OFFSET (24) 8698 #define PROTOCOL_IPV4 (0x0800) 8699 #define ETHERTYPE_ARP (0x0806) 8700 #define ETHERTYPE_IPV6 (0x86dd) 8701 8702 static int 8703 diag_icmpv6_checksum_set(uint8 *packet); 8704 static uint16 8705 diag_ipv6_checksum(uint8* packet, int packet_len); 8706 8707 8708 STATIC void 8709 diag_arp_callback(int unit, bcm_ptp_stack_id_t stack_id, int protocol, 8710 int src_addr_offset, int payload_offset, int msg_len, uint8 *msg) 8711 { 8712 int len; 8713 int required_len; 8714 int rv; 8715 8716 switch (protocol) { 8717 case ETHERTYPE_ARP: { 8718 uint8 *arp = msg + payload_offset; 8719 uint16 opcode = _bcm_ptp_uint16_read(arp + OPCODE_OFFSET); 8720 uint16 arp_protocol = _bcm_ptp_uint16_read(arp + PROTOCOL_OFFSET); 8721 8722 required_len = ARP_IPV4_LEN; 8723 len = msg_len - payload_offset; 8724 8725 if (len < required_len) { 8726 PTP_VERBOSE_CB(("ARP too short: %d vs %d\n", len, required_len)); 8727 return; 8728 } 8729 8730 if (opcode == ARP_REQUEST) { 8731 if (arp_protocol == PROTOCOL_IPV4) { 8732 uint32 addr = _bcm_ptp_uint32_read(arp + TARGET_IPV4_ADDR_OFFSET); 8733 int clock_num, port_idx; 8734 for (clock_num = 0; clock_num < PTP_MAX_STACKS_PER_UNIT; ++clock_num) { 8735 _bcm_ptp_clock_cache_t *clock = 8736 &_bcm_common_ptp_unit_array[unit].stack_array[stack_id].clock_array[clock_num]; 8737 8738 if (!clock->in_use) { 8739 continue; 8740 } 8741 8742 for (port_idx = 0; port_idx < clock->clock_info.num_ports; ++port_idx) { 8743 if (clock->port_info[port_idx].port_address.addr_type == bcmPTPUDPIPv4) { 8744 bcm_ip_t port_ip = _bcm_ptp_uint32_read(clock->port_info[port_idx].port_address.address); 8745 if (port_ip == addr) { 8746 /* Move incoming src to outgoing dest */ 8747 sal_memcpy(msg, msg+6, 6); 8748 /* put in "our" MAC as src MAC */ 8749 sal_memcpy(msg+6, clock->port_info[port_idx].mac, 6); 8750 8751 _bcm_ptp_uint16_write(arp + OPCODE_OFFSET, ARP_RESPONSE); 8752 8753 /* sender's MAC/IP -> target MAC/IP */ 8754 sal_memcpy(arp + TARGET_IPV4_MAC_OFFSET, arp + SENDER_IPV4_MAC_OFFSET, 10); 8755 8756 /* sender MAC */ 8757 sal_memcpy(arp + SENDER_IPV4_MAC_OFFSET, clock->port_info[port_idx].mac, 6); 8758 8759 _bcm_ptp_uint32_write(arp + SENDER_IPV4_ADDR_OFFSET, port_ip); /* sender IP */ 8760 8761 PTP_VERBOSE_CB(("Responding to ARP request for IP %08x\n", port_ip)); 8762 8763 if (BCM_FAILURE(rv = _bcm_ptp_tunnel_message_to_world(unit, stack_id, clock_num, msg_len, msg, 1))) { 8764 PTP_VERBOSE_CB(("Failed responding to ARP request for IP %08x\n", port_ip)); 8765 } 8766 8767 return; 8768 } 8769 } 8770 } 8771 } 8772 } 8773 } 8774 break; 8775 } 8776 8777 case ETHERTYPE_IPV6: { 8778 if (msg[payload_offset] == 135) { /* IPv6 ICMP type: Neighbor Solicitation */ 8779 uint8 *tgt_addr = msg + payload_offset + 8; /* Offset to target address in NS packet */ 8780 int dest_addr_offset = src_addr_offset + 16; 8781 int icmp_offset = payload_offset; 8782 int ipv6_offset = src_addr_offset - 8; 8783 8784 int clock_num, port_idx; 8785 for (clock_num = 0; clock_num < PTP_MAX_STACKS_PER_UNIT; ++clock_num) { 8786 _bcm_ptp_clock_cache_t *clock = 8787 &_bcm_common_ptp_unit_array[unit].stack_array[stack_id].clock_array[clock_num]; 8788 8789 if (!clock->in_use) { 8790 continue; 8791 } 8792 8793 for (port_idx = 0; port_idx < clock->clock_info.num_ports; ++port_idx) { 8794 if (clock->port_info[port_idx].port_address.addr_type == bcmPTPUDPIPv6) { 8795 if (sal_memcmp(tgt_addr, clock->port_info[port_idx].port_address.address, 16) == 0) { 8796 uint8 na[256]; 8797 8798 int na_len = icmp_offset + 32; /* 32 bytes for NA payload (incl 8 of option) */ 8799 uint8 unspecified[16] = {0}; /* the IPv6 unspecified address */ 8800 uint8 all_nodes[16] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 8801 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; 8802 int flags = 0; 8803 8804 PTP_VERBOSE_CB(("Got NS for our IP\n")); 8805 8806 if (msg_len > sizeof(na)) { 8807 PTP_VERBOSE_CB(("NS Too Big, dropping\n")); 8808 break; 8809 } 8810 /* start with a copy of the NS packet */ 8811 sal_memcpy(na, msg, msg_len); 8812 8813 /* L2 addresses */ 8814 sal_memcpy(na, msg+6, 6); /* copy src MAC on NS to dst MAC on NA */ 8815 sal_memcpy(na+6, clock->port_info[port_idx].mac, 6); /* copy port's MAC to src MAC on NA */ 8816 8817 /* L3 addresses */ 8818 8819 /* copy port's addr to src addr */ 8820 sal_memcpy(na + src_addr_offset, clock->port_info[port_idx].port_address.address, 16); 8821 8822 if (sal_memcmp(msg + src_addr_offset, unspecified, 16) == 0) { 8823 /* sender used the "unspecified" address, so send response to "all_nodes" */ 8824 sal_memcpy(na + dest_addr_offset, all_nodes, 16); 8825 flags = 0x40; /* set only the R (response) bit in flags */ 8826 } else { 8827 /* copy target's addr to dest addr */ 8828 sal_memcpy(na + dest_addr_offset, msg + src_addr_offset, 16); 8829 flags = 0x60; /* set R (response) and O (override) bits in flags */ 8830 } 8831 na[icmp_offset] = 136; /* NA */ 8832 na[icmp_offset + 4] = flags; 8833 8834 /* Option: include our link-layer address */ 8835 na[icmp_offset + 24] = 2; /* type 2: target link layer address */ 8836 na[icmp_offset + 25] = 1; /* length 1 (i.e. 1 set of 8 octets */ 8837 sal_memcpy(na + icmp_offset + 26, clock->port_info[port_idx].mac, 6); 8838 8839 /* set length */ 8840 na[ipv6_offset + 4] = 0; 8841 na[ipv6_offset + 5] = 32; /* 24 bytes + 8 bytes option */ 8842 8843 diag_icmpv6_checksum_set(na + ipv6_offset); 8844 8845 if (BCM_FAILURE(rv = _bcm_ptp_tunnel_message_to_world(unit, stack_id, clock_num, na_len, na, 1))) { 8846 PTP_VERBOSE_CB(("Failed responding to NS\n")); 8847 } 8848 break; 8849 } 8850 } 8851 } 8852 } 8853 } 8854 8855 return; 8856 } 8857 } 8858 } 8859 8860 #define BCMPTP_ND_NEIGHBOR_ADVERTISEMENT_ICMPV6_SIZE_OCTETS (32) 8861 #define BCMPTP_ND_NEIGHBOR_ADVERTISEMENT_IPV6_SIZE_OCTETS (72) 8862 8863 #define BCMPTP_ND_IPV6_PSEUDO_HEADER_SIZE_OCTETS (40) 8864 #define BCMPTP_ND_CHECKSUM_PACKET_SIZE_OCTETS (BCMPTP_ND_IPV6_PSEUDO_HEADER_SIZE_OCTETS + \ 8865 BCMPTP_ND_NEIGHBOR_ADVERTISEMENT_ICMPV6_SIZE_OCTETS) 8866 8867 #define BCMPTP_ND_IPV6_NEXT_HEADER_OFFSET_OCTETS (6) 8868 #define BCMPTP_ND_IPV6_SOURCE_IP_ADDRESS_OFFSET_OCTETS (8) 8869 #define BCMPTP_ND_IPV6_DESTINATION_IP_ADDRESS_OFFSET_OCTETS (24) 8870 8871 #define BCMPTP_ND_ICMPV6_OFFSET_OCTETS (40) 8872 #define BCMPTP_ND_ICMPV6_CHECKSUM_OFFSET_OCTETS (42) 8873 #define BCMPTP_ND_ICMPV6_TARGET_OFFSET_OCTETS (48) 8874 #define BCMPTP_ND_ICMPV6_OPTION_DATA_OFFSET (66) 8875 8876 #define BCMPTP_ND_NEXT_HEADER_ICMPV6 (0x3a) 8877 #define BCMPTP_ND_ICMPV6_TYPE_NEIGHBOR_SOLICITATION (0x87) 8878 #define BCMPTP_ND_ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT (0x88) 8879 8880 8881 8882 #define BCMPTP_IPV6_ADDR_SIZE_BYTES (16) 8883 8884 /* 8885 * Function: 8886 * _bcmptp_icmpv6_checksum_set() 8887 * Purpose: 8888 * Set checksum for an ICMPv6 Neighbor Advertisement message. 8889 * Parameters: 8890 * packet - (IN/OUT) ICMPv6 Neighbor Advertisement message. 8891 * Returns: 8892 * BCM_E_XXX - Function status. 8893 * Notes: 8894 */ 8895 static int 8896 diag_icmpv6_checksum_set(uint8 *packet) 8897 { 8898 int i; 8899 uint16 checksum; 8900 uint8 pseudo_plus_icmpv6[BCMPTP_ND_CHECKSUM_PACKET_SIZE_OCTETS] = {0}; 8901 8902 /* Zero existing checksum. */ 8903 sal_memset(packet + BCMPTP_ND_ICMPV6_CHECKSUM_OFFSET_OCTETS, 0, 8904 sizeof(uint16)); 8905 8906 /* 8907 * Make packet for checksum. 8908 * | IPv6 pseudo-header | ICMPv6 |. 8909 */ 8910 8911 /* 8912 * Insert IPv6 pseudo-header. 8913 * Ref. RFC 2460 - Internet Protocol, Version 6 (IPv6) Specification, 8914 * Sect. 8.1, Upper-Layer Checksums. 8915 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8916 * | | 8917 * + + 8918 * | | 8919 * + Source Address + 8920 * | | 8921 * + + 8922 * | | 8923 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8924 * | | 8925 * + + 8926 * | | 8927 * + Destination Address + 8928 * | | 8929 * + + 8930 * | | 8931 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8932 * | Upper-Layer Packet Length | 8933 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8934 * | zero | Next Header | 8935 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8936 */ 8937 sal_memcpy(pseudo_plus_icmpv6, 8938 packet + BCMPTP_ND_IPV6_SOURCE_IP_ADDRESS_OFFSET_OCTETS, 8939 BCMPTP_IPV6_ADDR_SIZE_BYTES); 8940 8941 i = BCMPTP_IPV6_ADDR_SIZE_BYTES; 8942 sal_memcpy(pseudo_plus_icmpv6 + i, 8943 packet + BCMPTP_ND_IPV6_DESTINATION_IP_ADDRESS_OFFSET_OCTETS, 8944 BCMPTP_IPV6_ADDR_SIZE_BYTES); 8945 8946 i += BCMPTP_IPV6_ADDR_SIZE_BYTES; 8947 _bcm_ptp_uint32_write(pseudo_plus_icmpv6 + i, 8948 BCMPTP_ND_NEIGHBOR_ADVERTISEMENT_ICMPV6_SIZE_OCTETS); 8949 8950 i += sizeof(uint32); 8951 _bcm_ptp_uint32_write(pseudo_plus_icmpv6 + i, BCMPTP_ND_NEXT_HEADER_ICMPV6); 8952 8953 /* Insert ICMPv6. */ 8954 i += sizeof(uint32); 8955 sal_memcpy(pseudo_plus_icmpv6 + i, 8956 packet + BCMPTP_ND_ICMPV6_OFFSET_OCTETS, 8957 BCMPTP_ND_NEIGHBOR_ADVERTISEMENT_ICMPV6_SIZE_OCTETS); 8958 8959 /* Calculate checksum. */ 8960 checksum = diag_ipv6_checksum(pseudo_plus_icmpv6, 8961 BCMPTP_ND_CHECKSUM_PACKET_SIZE_OCTETS); 8962 8963 /* Set checksum. */ 8964 _bcm_ptp_uint16_write(packet + BCMPTP_ND_ICMPV6_CHECKSUM_OFFSET_OCTETS, checksum); 8965 8966 return BCM_E_NONE; 8967 } 8968 8969 /* 8970 * Function: 8971 * _bcmptp_ipv6_checksum() 8972 * Purpose: 8973 * Calculate IPv6 checksum. 8974 * Parameters: 8975 * packet - (IN/OUT) Packet. 8976 * packet_len - (IN) Packet length (octets). 8977 * Returns: 8978 * BCM_E_XXX - Function status. 8979 * Notes: 8980 * Ref. RFC 2460 - Internet Protocol, Version 6 (IPv6) Specification, 8981 * Sect. 8.1, Upper-Layer Checksums. 8982 */ 8983 static uint16 8984 diag_ipv6_checksum(uint8* packet, int packet_len) 8985 { 8986 uint32 checksum = 0; 8987 8988 while (packet_len > 1) 8989 { 8990 /* Assemble words from consecutive octets and add to sum. */ 8991 checksum += (uint16)packet[0] << 8 | packet[1]; 8992 8993 /* 8994 * Increment pointer in packet. 8995 * Decrement remaining size. 8996 */ 8997 packet += sizeof(uint16); 8998 packet_len -= sizeof(uint16); 8999 } 9000 9001 /* Process odd octet. */ 9002 if (packet_len == 1) { 9003 checksum += (uint16)packet[0] << 8; 9004 } 9005 9006 /* Carry(ies). */ 9007 while (checksum >> 16) { 9008 checksum = (checksum >> 16) + (checksum & 0x0000ffff); 9009 } 9010 9011 /* 9012 * Result. 9013 * NOTE : Do not return zero checksum 9014 * (zero value set to 0xffff). 9015 */ 9016 if (checksum != 0xffff) { 9017 return ~checksum; 9018 } else { 9019 return checksum; 9020 } 9021 } 9022 9023 static const char *diag_ptp_state_change_reason_str[] = { 9024 "Startup, instance creation", 9025 "Port initialization", 9026 "Fault detected", 9027 "BMCA state transition", 9028 "Enable port management message", 9029 "Disable port management message", 9030 "Network interface re-initialization", 9031 "Timestamp difference, master-to-slave", 9032 "Unknown" 9033 }; 9034 9035 /* 9036 * Function: 9037 * diag_event_callback 9038 * Purpose: 9039 * Default event callback handler. 9040 * Parameters: 9041 * unit - (IN) Unit number. 9042 * stack_id - (IN) PTP stack ID. 9043 * clock_num - (IN) PTP clock number. 9044 * clock_port - (IN) PTP port number. 9045 * type - (IN) Callback function type. 9046 * msg - (IN) Callback message data. 9047 * user_data - (IN) Callback user data. 9048 * Returns: 9049 * BCM_E_XXX 9050 * Notes: 9051 */ 9052 STATIC int 9053 diag_event_callback( 9054 int unit, 9055 bcm_ptp_stack_id_t stack_id, 9056 int clock_num, 9057 uint32 clock_port, 9058 bcm_ptp_cb_type_t type, 9059 bcm_ptp_cb_msg_t *msg, 9060 void *user_data) 9061 { 9062 int rv = BCM_E_UNAVAIL; 9063 9064 uint16 event_type; 9065 bcm_ptp_protocol_t ucm_protocol; 9066 int eventID; 9067 sal_time_t host_time = sal_time(); 9068 char time_str[32]; 9069 int print_time = 0; 9070 #if defined(PTP_SAL_HAS_TIME) 9071 time_t host_time_as_time_t; 9072 struct tm *timestruct; 9073 #endif 9074 9075 if (diagshell_sync.synced) { 9076 #if defined(LONGS_ARE_64BITS) 9077 COMPILER_64_SUB_64(host_time, diagshell_sync.host_time); 9078 COMPILER_64_ADD_64(host_time, diagshell_sync.ptp_time.seconds); 9079 #else 9080 host_time -= diagshell_sync.host_time; 9081 host_time += COMPILER_64_LO(diagshell_sync.ptp_time.seconds); 9082 #endif 9083 } 9084 9085 #if defined(PTP_SAL_HAS_TIME) 9086 if (verboseEvents) { 9087 host_time_as_time_t = (time_t)host_time; 9088 timestruct = sal_localtime(&host_time_as_time_t); 9089 if (verboseEvents == 2) { 9090 print_time = sal_strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S ", timestruct); 9091 } else if (verboseEvents == 1) { 9092 print_time = sal_strftime(time_str, sizeof(time_str), "%H:%M:%S ", timestruct); 9093 } 9094 } 9095 #endif 9096 9097 if (!print_time) { 9098 sal_sprintf(time_str, "%u", (unsigned)host_time); 9099 } 9100 9101 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, clock_num, 9102 clock_port))) { 9103 PTP_ERROR_FUNC_CB("_bcm_ptp_function_precheck()"); 9104 return rv; 9105 } 9106 9107 /* Extract event type. */ 9108 event_type = _bcm_ptp_uint16_read(msg->data); 9109 9110 /* Move cursor to beginning of event data. */ 9111 msg->data = msg->data + sizeof(uint16); 9112 9113 switch ((_bcm_ptp_event_t)event_type) { 9114 case _bcm_ptp_state_change_event: 9115 if (verboseEvents == 2) { 9116 int code = msg->data[15]; 9117 if (code < _bcm_ptp_state_change_reason_startup || 9118 code > _bcm_ptp_state_change_reason_last) { 9119 code = _bcm_ptp_state_change_reason_last; 9120 } 9121 9122 ptp_cb_printf("Event %s: STATE CHANGE\n", time_str); 9123 /* 9124 * Event message data. 9125 * Octet 0 : Clock instance. 9126 * Octet 1...2 : Port number. 9127 * Octet 3...12 : Port identity. 9128 * Octet 13 : Port state. 9129 * Octet 14 : Prior port state. 9130 * Octet 15 : Port state change reason. 9131 */ 9132 ptp_cb_printf(" Instance : %d\n", msg->data[0]); 9133 ptp_cb_printf(" Port Number : %d\n", _bcm_ptp_uint16_read(msg->data+1)); 9134 ptp_cb_printf(" Port Identity: " 9135 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%04x\n", 9136 msg->data[3], msg->data[4], msg->data[5], msg->data[6], 9137 msg->data[7], msg->data[8], msg->data[9], msg->data[10], 9138 _bcm_ptp_uint16_read(msg->data + 3 + 9139 sizeof(bcm_ptp_clock_identity_t))); 9140 ptp_cb_printf("----------------------------------------" 9141 "----------------------------------------\n"); 9142 ptp_cb_printf(" Old Port State: %d (%s)\n", msg->data[14], 9143 diag_port_state_description(msg->data[14])); 9144 ptp_cb_printf(" New Port State: %d (%s)\n", msg->data[13], 9145 diag_port_state_description(msg->data[13])); 9146 9147 ptp_cb_printf(" Reason : %u (%s).\n", 9148 msg->data[15], diag_ptp_state_change_reason_str[code]); 9149 } else if (verboseEvents == 1) { 9150 int code = msg->data[15]; 9151 if (code < _bcm_ptp_state_change_reason_startup || 9152 code > _bcm_ptp_state_change_reason_last) { 9153 code = _bcm_ptp_state_change_reason_last; 9154 } 9155 9156 ptp_cb_printf("Event %s: STATE CHANGE: Port %d: %s -> %s [%s]\n", 9157 time_str, 9158 _bcm_ptp_uint16_read(msg->data+1), 9159 diag_port_state_description(msg->data[14]), 9160 diag_port_state_description(msg->data[13]), 9161 diag_ptp_state_change_reason_str[code]); 9162 } 9163 break; 9164 9165 case _bcm_ptp_master_change_event: 9166 if (verboseEvents == 2) { 9167 ptp_cb_printf("Event %s: MASTER CHANGE\n", time_str); 9168 /* 9169 * Event message data. 9170 * Octet 0 : Clock instance. 9171 * Octet 1...2 : Port number. 9172 * Octet 3...12 : Port identity. 9173 * Octet 13...22 : New master port identity. 9174 * Octet 23 : New master is-unicast Boolean. 9175 * Octet 24 : New master network protocol (unicast master). 9176 * Octet 25...26 : New master port address length (unicast master). 9177 * Octet 27...42 : New master port address (unicast master). 9178 * Octet 43...52 : Old master port identity. 9179 * Octet 53 : Old master is-unicast Boolean. 9180 * Octet 54 : Old master network protocol (unicast master). 9181 * Octet 55...56 : Old master port address length (unicast master). 9182 * Octet 57...72 : Old master port address (unicast master). 9183 * Octet 73...74 : new master's module number of card on which foreign master is seen. 9184 * Octet 75...76 : new master's physical port number of card on which foreign master is seen. 9185 * Octet 77...78 : old master's module number of card on which foreign master is seen. 9186 * Octet 79...80 : old master's physical port number of card on which foreign master is seen. 9187 */ 9188 ptp_cb_printf(" Instance : %d\n", msg->data[0]); 9189 ptp_cb_printf(" Port Number : %d\n", _bcm_ptp_uint16_read(msg->data+1)); 9190 ptp_cb_printf(" Port Identity: " 9191 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%04x\n", 9192 msg->data[3], msg->data[4], msg->data[5], msg->data[6], 9193 msg->data[7], msg->data[8], msg->data[9], msg->data[10], 9194 _bcm_ptp_uint16_read(msg->data + 3 + 9195 sizeof(bcm_ptp_clock_identity_t))); 9196 ptp_cb_printf("----------------------------------------" 9197 "----------------------------------------\n"); 9198 ptp_cb_printf(" New Master Properties\n"); 9199 ptp_cb_printf(" Port Identity : " 9200 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%04x\n", 9201 msg->data[13], msg->data[14], msg->data[15], msg->data[16], 9202 msg->data[17], msg->data[18], msg->data[19], msg->data[20], 9203 _bcm_ptp_uint16_read(msg->data + 13 + 9204 sizeof(bcm_ptp_clock_identity_t))); 9205 ptp_cb_printf(" Unicast or Multicast Master : %s\n", 9206 (msg->data[23]) ? "Unicast" : "Multicast"); 9207 9208 ucm_protocol = msg->data[24]; 9209 9210 ptp_cb_printf(" Master Protocol: %u", ucm_protocol); 9211 if (ucm_protocol == bcmPTPIEEE8023) { 9212 ptp_cb_printf(" (Ethernet Layer 2)\n"); 9213 ptp_cb_printf(" Multicast Master Address : " 9214 "%02x:%02x:%02x:%02x:%02x:%02x (MAC)\n", 9215 msg->data[27], msg->data[28], msg->data[29], msg->data[30], 9216 msg->data[31], msg->data[32]); 9217 } else if (ucm_protocol == bcmPTPUDPIPv4) { 9218 ptp_cb_printf(" (Ethernet/UDP/IPv4)\n"); 9219 ptp_cb_printf(" UC Master Address : %u.%u.%u.%u (IPv4)\n", 9220 msg->data[27], msg->data[28], msg->data[29], msg->data[30]); 9221 } else if (ucm_protocol == bcmPTPUDPIPv6){ 9222 ptp_cb_printf(" (Ethernet/UDP/IPv6)\n"); 9223 ptp_cb_printf(" UC Master Address : " 9224 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 9225 "%02x%02x:%02x%02x:%02x%02x:%02x%02x (IPv6)\n", 9226 msg->data[27], msg->data[28], msg->data[29], msg->data[30], 9227 msg->data[31], msg->data[32], msg->data[33], msg->data[34], 9228 msg->data[35], msg->data[36], msg->data[37], msg->data[38], 9229 msg->data[39], msg->data[40], msg->data[41], msg->data[42]); 9230 } else { 9231 ptp_cb_printf(" (Unknown)\n"); 9232 } 9233 9234 ptp_cb_printf("\n"); 9235 ptp_cb_printf(" Old Master Properties\n"); 9236 ptp_cb_printf(" Port Identity : " 9237 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%04x\n", 9238 msg->data[43], msg->data[44], msg->data[45], msg->data[46], 9239 msg->data[47], msg->data[48], msg->data[49], msg->data[50], 9240 _bcm_ptp_uint16_read(msg->data + 43 + 9241 sizeof(bcm_ptp_clock_identity_t))); 9242 ptp_cb_printf(" Unicast or Mutlicast Master : %s\n", 9243 (msg->data[53]) ? "Unicast" : "Multicast"); 9244 9245 ucm_protocol = msg->data[54]; 9246 9247 ptp_cb_printf(" Master Protocol: %u", ucm_protocol); 9248 if (ucm_protocol == bcmPTPIEEE8023) { 9249 ptp_cb_printf(" (Ethernet Layer 2)\n"); 9250 ptp_cb_printf(" Multicast Master Address : " 9251 "%02x:%02x:%02x:%02x:%02x:%02x (MAC)\n", 9252 msg->data[57], msg->data[58], msg->data[59], msg->data[60], 9253 msg->data[61], msg->data[62]); 9254 } else if (ucm_protocol == bcmPTPUDPIPv4) { 9255 ptp_cb_printf(" (Ethernet/UDP/IPv4)\n"); 9256 ptp_cb_printf(" UC Master Address : %u.%u.%u.%u (IPv4)\n", 9257 msg->data[57], msg->data[58], msg->data[59], msg->data[60]); 9258 } else if (ucm_protocol == bcmPTPUDPIPv6) { 9259 ptp_cb_printf(" (Ethernet/UDP/IPv6)\n"); 9260 ptp_cb_printf(" UC Master Address : " 9261 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 9262 "%02x%02x:%02x%02x:%02x%02x:%02x%02x (IPv6)\n", 9263 msg->data[57], msg->data[58], msg->data[59], msg->data[60], 9264 msg->data[61], msg->data[62], msg->data[63], msg->data[64], 9265 msg->data[65], msg->data[66], msg->data[67], msg->data[68], 9266 msg->data[69], msg->data[70], msg->data[71], msg->data[72]); 9267 } else { 9268 ptp_cb_printf(" (Unknown)\n"); 9269 } 9270 9271 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 9272 ptp_cb_printf(" New master's Module Number: %d\n", _bcm_ptp_uint16_read(msg->data + 73)); 9273 ptp_cb_printf(" New master's Physical Port Number: %d\n", _bcm_ptp_uint16_read(msg->data + 75)); 9274 9275 ptp_cb_printf(" Old master's Module Number: %d\n", _bcm_ptp_uint16_read(msg->data + 77)); 9276 ptp_cb_printf(" Old master's Physical Port Number: %d\n", _bcm_ptp_uint16_read(msg->data + 79)); 9277 } 9278 9279 } else if (verboseEvents == 1) { 9280 char port_addr[32]; /* needs space for 8 * 3 + 4 + null */ 9281 char addr[50] = "??"; /* IPv6 -> 16 * 3 + null */ 9282 9283 sal_sprintf(port_addr, 9284 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%04x", 9285 msg->data[13], msg->data[14], msg->data[15], msg->data[16], 9286 msg->data[17], msg->data[18], msg->data[19], msg->data[20], 9287 _bcm_ptp_uint16_read(msg->data + 13 + 9288 sizeof(bcm_ptp_clock_identity_t))); 9289 ucm_protocol = msg->data[24]; 9290 if (ucm_protocol == bcmPTPIEEE8023) { 9291 sal_sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", 9292 msg->data[27], msg->data[28], msg->data[29], msg->data[30], 9293 msg->data[31], msg->data[32]); 9294 } else if (ucm_protocol == bcmPTPUDPIPv4) { 9295 sal_sprintf(addr, "%u.%u.%u.%u", 9296 msg->data[27], msg->data[28], msg->data[29], msg->data[30]); 9297 } else if (ucm_protocol == bcmPTPUDPIPv6){ 9298 sal_sprintf(addr, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 9299 "%02x%02x:%02x%02x:%02x%02x:%02x%02x", 9300 msg->data[27], msg->data[28], msg->data[29], msg->data[30], 9301 msg->data[31], msg->data[32], msg->data[33], msg->data[34], 9302 msg->data[35], msg->data[36], msg->data[37], msg->data[38], 9303 msg->data[39], msg->data[40], msg->data[41], msg->data[42]); 9304 } 9305 ptp_cb_printf("Event %s: MASTER CHANGE %s [%s]\n", time_str, addr, port_addr); 9306 } 9307 break; 9308 9309 case _bcm_ptp_master_avail_event: 9310 case _bcm_ptp_master_unavail_event: 9311 if (verboseEvents == 2) { 9312 ptp_cb_printf("Event %s: MASTER %sAVAILABLE\n", time_str, 9313 (event_type == _bcm_ptp_master_unavail_event) ? "UN" : ""); 9314 /* 9315 * Event message data. 9316 * Octet 0 : Clock instance. 9317 * Octet 1...2 : Port number. 9318 * Octet 3...12 : Port identity. 9319 * Octet 13...22 : Foreign master port identity. 9320 * Octet 23 : Foreign master is-acceptable Boolean. 9321 * Octet 24 : Foreign master is-unicast Boolean. 9322 * Octet 25 : Foreign master network protocol (unicast foreign master). 9323 * Octet 26...27 : Foreign master port address length (unicast foreign master). 9324 * Octet 28...43 : Foreign master port address (unicast foreign master). 9325 * Octet 44...45: module number of card on which foreign master is seen. 9326 * Octet 46...47: physical port number of card on which Foreign master is seen. 9327 */ 9328 ptp_cb_printf(" Instance : %d\n", msg->data[0]); 9329 ptp_cb_printf(" Port Number : %d\n", _bcm_ptp_uint16_read(msg->data+1)); 9330 ptp_cb_printf(" Port Identity: " 9331 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%04x\n", 9332 msg->data[3], msg->data[4], msg->data[5], msg->data[6], 9333 msg->data[7], msg->data[8], msg->data[9], msg->data[10], 9334 _bcm_ptp_uint16_read(msg->data + 3 + 9335 sizeof(bcm_ptp_clock_identity_t))); 9336 ptp_cb_printf("----------------------------------------" 9337 "----------------------------------------\n"); 9338 ptp_cb_printf(" Foreign Master Properties\n"); 9339 ptp_cb_printf(" Port Identity : " 9340 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%04x\n", 9341 msg->data[13], msg->data[14], msg->data[15], msg->data[16], 9342 msg->data[17], msg->data[18], msg->data[19], msg->data[20], 9343 _bcm_ptp_uint16_read(msg->data + 13 + 9344 sizeof(bcm_ptp_clock_identity_t))); 9345 ptp_cb_printf(" Acceptable Master : %u\n", msg->data[23]); 9346 ptp_cb_printf(" Unicast or Multicast Master : %s\n", 9347 (msg->data[24]) ? "Unicast" : "Multicast"); 9348 9349 ucm_protocol = msg->data[25]; 9350 9351 ptp_cb_printf(" Master Protocol: %u", ucm_protocol); 9352 if (ucm_protocol == bcmPTPIEEE8023) { 9353 ptp_cb_printf(" (Ethernet Layer 2)\n"); 9354 ptp_cb_printf(" Multicast Master Address : " 9355 "%02x:%02x:%02x:%02x:%02x:%02x (MAC)\n", 9356 msg->data[28], msg->data[29], msg->data[30], msg->data[31], 9357 msg->data[32], msg->data[33]); 9358 } else if (ucm_protocol == bcmPTPUDPIPv4) { 9359 ptp_cb_printf(" (Ethernet/UDP/IPv4)\n"); 9360 ptp_cb_printf(" UC Master Address : %u.%u.%u.%u (IPv4)\n", 9361 msg->data[28], msg->data[29], msg->data[30], msg->data[31]); 9362 } else if (ucm_protocol== bcmPTPUDPIPv6) { 9363 ptp_cb_printf(" (Ethernet/UDP/IPv6)\n"); 9364 ptp_cb_printf(" UC Master Address : " 9365 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 9366 "%02x%02x:%02x%02x:%02x%02x:%02x%02x (IPv6)\n", 9367 msg->data[28], msg->data[29], msg->data[30], msg->data[31], 9368 msg->data[32], msg->data[33], msg->data[34], msg->data[35], 9369 msg->data[36], msg->data[37], msg->data[38], msg->data[39], 9370 msg->data[40], msg->data[41], msg->data[42], msg->data[43]); 9371 } else { 9372 ptp_cb_printf(" (Unknown)\n"); 9373 } 9374 9375 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 9376 ptp_cb_printf(" Module Number: %d\n", _bcm_ptp_uint16_read(msg->data + 44)); 9377 ptp_cb_printf(" Physical Port Number: %d\n", _bcm_ptp_uint16_read(msg->data + 46)); 9378 } 9379 9380 } else if (verboseEvents == 1) { 9381 char port_addr[32]; /* needs space for 8 * 3 + 4 + null */ 9382 char addr[50] = "??"; /* IPv6 -> 16 * 3 + null */ 9383 9384 sal_sprintf(port_addr, 9385 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%04x", 9386 msg->data[13], msg->data[14], msg->data[15], msg->data[16], 9387 msg->data[17], msg->data[18], msg->data[19], msg->data[20], 9388 _bcm_ptp_uint16_read(msg->data + 13 + 9389 sizeof(bcm_ptp_clock_identity_t))); 9390 9391 ucm_protocol = msg->data[25]; 9392 if (ucm_protocol == bcmPTPIEEE8023) { 9393 sal_sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", 9394 msg->data[28], msg->data[29], msg->data[30], msg->data[31], 9395 msg->data[32], msg->data[33]); 9396 } else if (ucm_protocol == bcmPTPUDPIPv4) { 9397 sal_sprintf(addr, "%u.%u.%u.%u", 9398 msg->data[28], msg->data[29], msg->data[30], msg->data[31]); 9399 } else if (ucm_protocol == bcmPTPUDPIPv6){ 9400 sal_sprintf(addr, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 9401 "%02x%02x:%02x%02x:%02x%02x:%02x%02x", 9402 msg->data[28], msg->data[29], msg->data[30], msg->data[31], 9403 msg->data[32], msg->data[33], msg->data[34], msg->data[35], 9404 msg->data[36], msg->data[37], msg->data[38], msg->data[39], 9405 msg->data[40], msg->data[41], msg->data[42], msg->data[43]); 9406 } 9407 9408 ptp_cb_printf("Event %s: MASTER CHANGE %s [%s]\n", time_str, addr, port_addr); 9409 } 9410 break; 9411 9412 case _bcm_ptp_slave_avail_event: 9413 case _bcm_ptp_slave_unavail_event: 9414 if (verboseEvents == 2) { 9415 ptp_cb_printf("Event %s: SLAVE %sAVAILABLE\n", time_str, 9416 (event_type == _bcm_ptp_slave_unavail_event) ? "UN" : ""); 9417 /* 9418 * Event message data. 9419 * Octet 0 : Clock instance. 9420 * Octet 1...2 : Port number. 9421 * Octet 3...12 : Clock ID. 9422 * Octet 25 : Foreign slave network protocol (unicast foreign master). 9423 * Octet 26...27: Foreign slave port address length (unicast foreign master). 9424 * Octet 28...43: Foreign slave port address (unicast foreign master). 9425 */ 9426 9427 ptp_cb_printf(" Instance : %d\n", msg->data[0]); 9428 ptp_cb_printf(" Port Number : %d\n", _bcm_ptp_uint16_read(msg->data+1)); 9429 ptp_cb_printf(" Clock Identity: " 9430 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 9431 msg->data[3], msg->data[4], msg->data[5], msg->data[6], 9432 msg->data[7], msg->data[8], msg->data[9], msg->data[10]); 9433 eventID = msg->data[24]; 9434 ptp_cb_printf(" Event ID: %u", eventID); 9435 ucm_protocol = msg->data[25]; 9436 ptp_cb_printf(" Protocol: %u", ucm_protocol); 9437 if (ucm_protocol == bcmPTPIEEE8023) { 9438 ptp_cb_printf(" (Ethernet Layer 2)\n"); 9439 ptp_cb_printf(" Slave Address: " 9440 "%02x:%02x:%02x:%02x:%02x:%02x\n", 9441 msg->data[28], msg->data[29], msg->data[30], msg->data[31], 9442 msg->data[32], msg->data[33]); 9443 } else if (ucm_protocol == bcmPTPUDPIPv4) { 9444 ptp_cb_printf(" (Ethernet/UDP/IPv4)\n"); 9445 ptp_cb_printf(" Slave Address : %u.%u.%u.%u (IPv4)\n", 9446 msg->data[28], msg->data[29], msg->data[30], msg->data[31]); 9447 } else if (ucm_protocol== bcmPTPUDPIPv6) { 9448 ptp_cb_printf(" (Ethernet/UDP/IPv6)\n"); 9449 ptp_cb_printf(" Slave Address : " 9450 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 9451 "%02x%02x:%02x%02x:%02x%02x:%02x%02x (IPv6)\n", 9452 msg->data[28], msg->data[29], msg->data[30], msg->data[31], 9453 msg->data[32], msg->data[33], msg->data[34], msg->data[35], 9454 msg->data[36], msg->data[37], msg->data[38], msg->data[39], 9455 msg->data[40], msg->data[41], msg->data[42], msg->data[43]); 9456 } else { 9457 ptp_cb_printf(" (Unknown)\n"); 9458 } 9459 9460 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 9461 ptp_cb_printf(" Module Number: %d\n", _bcm_ptp_uint16_read(msg->data + 44)); 9462 ptp_cb_printf(" Physical Port Number: %d\n", _bcm_ptp_uint16_read(msg->data + 46)); 9463 } 9464 9465 9466 } 9467 9468 break; 9469 9470 case _bcm_ptp_top_oom_event: 9471 if (verboseEvents > 0) { 9472 9473 9474 ptp_cb_printf("Event %s: ToP OUT-OF-MEMORY\n", time_str); 9475 /* 9476 * Event message data. 9477 * Octet 0...3 : Minimum free memory (bytes). 9478 * Octet 4...7 : Free ordinary blocks (bytes). 9479 */ 9480 ptp_cb_printf(" Min. Free Memory: %u (bytes)\n", 9481 _bcm_ptp_uint32_read(msg->data)); 9482 ptp_cb_printf(" Ord. Blocks Free: %u (bytes)\n", 9483 _bcm_ptp_uint32_read(msg->data + sizeof(uint32))); 9484 } 9485 break; 9486 9487 case _bcm_ptp_top_watchdog_event: 9488 break; 9489 9490 case _bcm_ptp_top_ready_event: 9491 if (verboseEvents > 0) { 9492 ptp_cb_printf("Event %s: ToP READY\n", time_str); 9493 } 9494 break; 9495 9496 case _bcm_ptp_top_misc_event: 9497 if (verboseEvents > 0) { 9498 ptp_cb_printf("Event %s: ToP MISC\n", time_str); 9499 /* 9500 * Event message data. 9501 * Octet 0 : Reason code 9502 */ 9503 switch (msg->data[0]) 9504 { 9505 case _bcm_ptp_top_misc_reason_anncFlagChange: 9506 ptp_cb_printf(" Reason Code: %d\n", msg->data[0]); 9507 ptp_cb_printf(" PrevFlags : 0x%x\n", _bcm_ptp_uint32_read(msg->data+1)); 9508 ptp_cb_printf(" NewFlags : 0x%x\n", _bcm_ptp_uint32_read(msg->data+5)); 9509 default: 9510 break; 9511 } 9512 } 9513 break; 9514 9515 case _bcm_ptp_top_tod_avail_event: 9516 if (verboseEvents > 0) { 9517 ptp_cb_printf("Event %s: ToP ToD Available\n", time_str); 9518 } 9519 break; 9520 9521 case _bcm_ptp_top_tod_unavail_event: 9522 if (verboseEvents > 0) { 9523 ptp_cb_printf("Event %s: ToP ToD Unavailable\n", time_str); 9524 } 9525 break; 9526 9527 case _bcm_ptp_ieee1588_warn_event: 9528 if (verboseEvents == 2) { 9529 ptp_cb_printf("Event %s: IEEE Std. 1588-2008 WARNING\n", time_str); 9530 /* 9531 * Event message data. 9532 * Octet 0 : Clock instance. 9533 * Octet 1...2 : Port number. 9534 * Octet 3...12 : Port identity. 9535 * Octet 13 : IEEE Std. 1588-2008 warning reason code. 9536 * Octet 14...N : Reason-dependent message data. 9537 */ 9538 ptp_cb_printf(" Instance : %d\n", msg->data[0]); 9539 ptp_cb_printf(" Port Number : %d\n", _bcm_ptp_uint16_read(msg->data+1)); 9540 ptp_cb_printf(" Port Identity: " 9541 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%04x\n", 9542 msg->data[3], msg->data[4], msg->data[5], msg->data[6], 9543 msg->data[7], msg->data[8], msg->data[9], msg->data[10], 9544 _bcm_ptp_uint16_read(msg->data + 3 + 9545 sizeof(bcm_ptp_clock_identity_t))); 9546 ptp_cb_printf("----------------------------------------" 9547 "----------------------------------------\n"); 9548 ptp_cb_printf(" Warning Reason: %u (%s)\n", msg->data[13], 9549 diag_ieee1588_warn_reason_description(msg->data[13])); 9550 ptp_cb_printf("\n"); 9551 9552 switch (msg->data[13]) { 9553 case _bcm_ptp_ieee1588_warn_reason_logAnnounceInterval: 9554 /* 9555 * Non-uniform logAnnounceInterval in a PTP domain. 9556 * Octet 0...13 : IEEE Std. 1588-2008 warning common data. 9557 * Octet 14...23 : Foreign master port identity. 9558 * Octet 24 : Foreign master is-acceptable Boolean. 9559 * Octet 25 : Foreign master is-unicast Boolean. 9560 * Octet 26 : Foreign master network protocol (unicast foreign master). 9561 * Octet 27...28 : Foreign master port address length (unicast foreign master). 9562 * Octet 29...44 : Foreign master port address (unicast foreign master). 9563 * Octet 45 : Foreign master logAnnounceInterval. 9564 */ 9565 ptp_cb_printf(" Foreign Master Properties\n"); 9566 ptp_cb_printf(" Port Identity : " 9567 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%04x\n", 9568 msg->data[14], msg->data[15], msg->data[16], msg->data[17], 9569 msg->data[18], msg->data[19], msg->data[20], msg->data[21], 9570 _bcm_ptp_uint16_read(msg->data + 14 + 9571 sizeof(bcm_ptp_clock_identity_t))); 9572 ptp_cb_printf(" Acceptable Master : %u\n", msg->data[24]); 9573 ptp_cb_printf(" Unicast Master : %u\n", msg->data[25]); 9574 9575 if (msg->data[25]) { 9576 ucm_protocol = msg->data[26]; 9577 9578 ptp_cb_printf(" UC Master Protocol: %u", ucm_protocol); 9579 if (ucm_protocol == bcmPTPIEEE8023) { 9580 ptp_cb_printf(" (Ethernet Layer 2)\n"); 9581 } else if (ucm_protocol == bcmPTPUDPIPv4) { 9582 ptp_cb_printf(" (Ethernet/UDP/IPv4)\n"); 9583 ptp_cb_printf(" UC Master Address : %u.%u.%u.%u (IPv4)\n", 9584 msg->data[29], msg->data[30], msg->data[31], msg->data[32]); 9585 } else if (ucm_protocol == bcmPTPUDPIPv6) { 9586 ptp_cb_printf(" (Ethernet/UDP/IPv6)\n"); 9587 ptp_cb_printf(" UC Master Address : " 9588 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 9589 "%02x%02x:%02x%02x:%02x%02x:%02x%02x (IPv6)\n", 9590 msg->data[29], msg->data[30], msg->data[31], msg->data[32], 9591 msg->data[33], msg->data[34], msg->data[35], msg->data[36], 9592 msg->data[37], msg->data[38], msg->data[39], msg->data[40], 9593 msg->data[41], msg->data[42], msg->data[43], msg->data[44]); 9594 } else { 9595 ptp_cb_printf(" UC Master Protocol : %u (Unknown)\n", ucm_protocol); 9596 } 9597 } 9598 ptp_cb_printf(" logAnnounceInterval: %d\n", (int8)msg->data[45]); 9599 break; 9600 9601 default: 9602 ; 9603 } 9604 } else if (verboseEvents == 1) { 9605 ptp_cb_printf("Event %s: Warning: %s", time_str, 9606 diag_ieee1588_warn_reason_description(msg->data[13])); 9607 } 9608 break; 9609 9610 case _bcm_ptp_servo_state_event: 9611 if (verboseEvents == 2) { 9612 ptp_cb_printf("Event %s: SERVO STATE\n", time_str); 9613 ptp_cb_printf(" Instance : %d\n", msg->data[0]); 9614 ptp_cb_printf(" Old State : %d (%s)\n", msg->data[2], 9615 diag_servo_state_description(msg->data[2])); 9616 ptp_cb_printf(" New State : %d (%s)\n", msg->data[1], 9617 diag_servo_state_description(msg->data[1])); 9618 } else if (verboseEvents == 1) { 9619 ptp_cb_printf("Event %s: SERVO STATE %s -> %s\n", 9620 time_str, 9621 diag_servo_state_description(msg->data[2]), 9622 diag_servo_state_description(msg->data[1])); 9623 } 9624 break; 9625 9626 case _bcm_ptp_pps_in_state_event: 9627 if (verboseEvents == 2) { 9628 ptp_cb_printf("Event %s: PPS-IN STATE\n", time_str); 9629 ptp_cb_printf(" State : %d (%s)\n", msg->data[0], 9630 diag_pps_in_state_description(msg->data[0])); 9631 } else if (verboseEvents == 1) { 9632 ptp_cb_printf("Event %s: PPS-IN STATE : %s\n", time_str, 9633 diag_pps_in_state_description(msg->data[0])); 9634 } 9635 break; 9636 9637 case _bcm_ptp_servo_log_event: 9638 { 9639 /* unsigned time_sec_hi = _bcm_ptp_uint32_read(msg->data+1); */ 9640 unsigned time_sec_lo = _bcm_ptp_uint32_read(msg->data+5); 9641 unsigned event_id = _bcm_ptp_uint16_read(msg->data+9); 9642 unsigned severity_num = msg->data[11]; 9643 unsigned state_num = msg->data[12]; 9644 unsigned aux = _bcm_ptp_uint32_read(msg->data+13); 9645 char *servo_msg = (char*)msg->data+17; 9646 const char *state[4] = {"CLR", "SET", "TRANS", "OTHER"}; 9647 const char *severity[8] = {"EMRG", "ALRT", "CRIT", "ERR", "WARN", "NOTC", "INFO", "DBG"}; 9648 9649 if (verboseEvents == 2) { 9650 ptp_cb_printf("Event %s: SERVO LOG\n", time_str); 9651 ptp_cb_printf(" %u: %u %s %s (%u)\n", time_sec_lo, event_id, 9652 severity[severity_num], state[state_num], aux); 9653 ptp_cb_printf(" <%s>\n", servo_msg); 9654 } else if (verboseEvents == 1) { 9655 ptp_cb_printf("Event %s: SERVO %s %s <%s> (%d)\n", time_str, 9656 severity[severity_num], state[state_num], servo_msg, aux); 9657 } 9658 9659 } 9660 break; 9661 9662 case _bcm_ptp_servo_lock_event: 9663 if (verboseEvents == 2) { 9664 ptp_cb_printf("Event %s: SERVO LOCK STATUS\n", time_str); 9665 ptp_cb_printf(" Instance : %d\n", msg->data[0]); 9666 ptp_cb_printf(" Old Status : %d (%s)\n", msg->data[2], 9667 diag_servo_lock_status_description(msg->data[2])); 9668 ptp_cb_printf(" New Status : %d (%s)\n", msg->data[1], 9669 diag_servo_lock_status_description(msg->data[1])); 9670 } else if (verboseEvents == 1) { 9671 ptp_cb_printf("Event %s: SERVO LOCK STATUS %s -> %s\n", 9672 time_str, 9673 diag_servo_lock_status_description(msg->data[2]), 9674 diag_servo_lock_status_description(msg->data[1])); 9675 } 9676 break; 9677 9678 case _bcm_ptp_synce_loss_event: 9679 if (verboseEvents == 2) { 9680 ptp_cb_printf("Event %s: SYNCE LOSS \n", time_str); 9681 ptp_cb_printf(" Port : %d\n", msg->data[0]); 9682 } 9683 break; 9684 9685 9686 default: 9687 ptp_cb_printf("Unexpected event %s:, type %d\n", time_str, event_type); 9688 9689 break; 9690 } 9691 /* Rewind cursor. */ 9692 msg->data = msg->data - sizeof(uint16); 9693 9694 return rv; 9695 } 9696 9697 /* 9698 * Function: 9699 * diag_management_callback 9700 * Purpose: 9701 * Default forwarded (tunneled) PTP management message callback handler. 9702 * Parameters: 9703 * unit - (IN) Unit number. 9704 * stack_id - (IN) PTP stack ID. 9705 * clock_num - (IN) PTP clock number. 9706 * clock_port - (IN) PTP port number. 9707 * type - (IN) Callback function type. 9708 * msg - (IN) Callback message data. 9709 * user_data - (IN) Callback user data. 9710 * Returns: 9711 * BCM_E_XXX (if failure) 9712 * bcmPTPCallbackAccept (if success) 9713 * Notes: 9714 */ 9715 STATIC int 9716 diag_management_callback( 9717 int unit, 9718 bcm_ptp_stack_id_t stack_id, 9719 int clock_num, 9720 uint32 clock_port, 9721 bcm_ptp_cb_type_t type, 9722 bcm_ptp_cb_msg_t *msg, 9723 void *user_data) 9724 { 9725 int rv = BCM_E_UNAVAIL; 9726 9727 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, clock_num, 9728 clock_port))) { 9729 PTP_ERROR_FUNC_CB("_bcm_ptp_function_precheck()"); 9730 return rv; 9731 } 9732 9733 ptp_cb_printf("Management callback (Unit = %d, PTP Stack = %d)\n", unit, stack_id); 9734 9735 return bcmPTPCallbackAccept; 9736 } 9737 9738 9739 /* 9740 * Function: 9741 * diag_signaling_arbiter() 9742 * Purpose: 9743 * Reference implementation to accept/reject an incoming PTP signaling message. 9744 * Parameters: 9745 * unit - (IN) Unit number. 9746 * amsg - (IN/OUT) Arbiter message data. 9747 * user_data - (IN) User data. 9748 * Returns: 9749 * bcmPTPCallbackAccept - Criteria met; accept PTP signaling message. 9750 * bcmPTPCallbackReject - Criteria not met; reject PTP signaling message. 9751 * Note: 9752 * Reference implementation: 9753 * Filter message based on PTP domain, interval, and duration. 9754 * Set Tx timestamp mechanism to the default for the platform. 9755 */ 9756 bcm_ptp_callback_t diag_signaling_arbiter( 9757 int unit, 9758 bcm_ptp_cb_signaling_arbiter_msg_t *amsg, 9759 void * user_data) 9760 { 9761 uint32 durationField_min; 9762 uint32 durationField_max; 9763 bcm_ptp_clock_port_info_t port_data; 9764 9765 9766 /* 9767 * Reject unicast negotiation requests if arbiter deny-all 9768 * mechanism is enabled or local clock is slave-only clock. 9769 */ 9770 if ((PTR_TO_INT(user_data) & ARBITER_DENY_FLAG) || 9771 (amsg->clock_info->slaveonly)) { 9772 return bcmPTPCallbackReject; 9773 } 9774 9775 /* 9776 * Check logInterMessagePeriod against values stored in clock instance. 9777 * Reference implementation: Reject PTP signaling messages that request 9778 * intervals outside PTP profile range. 9779 */ 9780 switch (*(amsg->messageType)) { 9781 case (bcmPTP_MESSAGE_TYPE_ANNOUNCE): 9782 if ((*(amsg->logInterMessagePeriod) < amsg->clock_info->log_announce_interval_minimum) || 9783 (*(amsg->logInterMessagePeriod) > amsg->clock_info->log_announce_interval_maximum)) { 9784 9785 PTP_VERBOSE_CB(("%s() failed %s\n", FUNCTION_NAME(), "Log announce interval outside PTP profile range.\n")); 9786 return bcmPTPCallbackReject; 9787 } 9788 break; 9789 9790 case (bcmPTP_MESSAGE_TYPE_SYNC): 9791 if ((*(amsg->logInterMessagePeriod) < amsg->clock_info->log_sync_interval_minimum) || 9792 (*(amsg->logInterMessagePeriod) > amsg->clock_info->log_sync_interval_maximum)) { 9793 9794 PTP_VERBOSE_CB(("%s() failed %s\n", FUNCTION_NAME(), "Log sync interval outside PTP profile range.\n")); 9795 return bcmPTPCallbackReject; 9796 } 9797 break; 9798 9799 case (bcmPTP_MESSAGE_TYPE_DELAY_RESP): 9800 if ((*(amsg->logInterMessagePeriod) < amsg->clock_info->log_min_delay_req_interval_minimum) || 9801 (*(amsg->logInterMessagePeriod) > amsg->clock_info->log_min_delay_req_interval_maximum)) { 9802 9803 PTP_VERBOSE_CB(("%s() failed %s\n", FUNCTION_NAME(), "Log delay interval outside PTP profile range.\n")); 9804 return bcmPTPCallbackReject; 9805 } 9806 break; 9807 9808 default: 9809 return bcmPTPCallbackReject; 9810 } 9811 9812 /* 9813 * Check durationField against PTP profile range. 9814 * Reference implementation: Reject PTP signaling messages that request 9815 * a duration outside PTP profile range. 9816 */ 9817 if (BCM_FAILURE(bcm_ptp_unicast_request_duration_min_get(unit, 9818 amsg->ptp_id, amsg->clock_num, amsg->port_num, &durationField_min)) || 9819 BCM_FAILURE(bcm_ptp_unicast_request_duration_max_get(unit, 9820 amsg->ptp_id, amsg->clock_num, amsg->port_num, &durationField_max)) || 9821 *(amsg->durationField) < durationField_min || *(amsg->durationField) > durationField_max) { 9822 9823 PTP_VERBOSE_CB(("%s() failed %s\n", FUNCTION_NAME(), "durationField outside PTP profile range.\n")); 9824 return bcmPTPCallbackReject; 9825 } 9826 9827 if (BCM_FAILURE(bcm_ptp_clock_port_info_get(unit, amsg->ptp_id, amsg->clock_num, 9828 amsg->port_num, &port_data))) { 9829 PTP_VERBOSE_CB(("%s() failed %s\n", FUNCTION_NAME(), "failed to get port data.\n")); 9830 return bcmPTPCallbackReject; 9831 } 9832 9833 #if defined(PTP_KEYSTONE_STACK) 9834 amsg->slave->tx_timestamp_mech = bcmPTPToPTimestamps; 9835 #else 9836 amsg->slave->tx_timestamp_mech = port_data.rx_timestamp_mechanism; 9837 #endif 9838 9839 /* Accept the default L2 header, which is simply the incoming L2 header with the MAC fields reversed */ 9840 9841 return bcmPTPCallbackAccept; 9842 } 9843 9844 9845 /* 9846 * Function: 9847 * diag_ctdev_alarm_callback 9848 * Purpose: 9849 * C-TDEV alarm callback example. 9850 * Use ITU-T G.823 SEC TDEV mask to characterize pass/fail. 9851 * Parameters: 9852 * unit - (IN) Unit number. 9853 * ptp_id - (IN) PTP stack ID. 9854 * clock_num - (IN) PTP clock number. 9855 * alarm_data - (IN) C-TDEV alarm data. 9856 * Returns: 9857 * BCM_E_XXX - Function status. 9858 * Notes: 9859 */ 9860 STATIC int 9861 diag_ctdev_alarm_callback( 9862 int unit, 9863 bcm_ptp_stack_id_t ptp_id, 9864 int clock_num, 9865 bcm_ptp_ctdev_alarm_data_t *ctdev_alarm_data) 9866 { 9867 int i; 9868 uint32 g823_mask_psec[BCM_PTP_CTDEV_NUM_TIMESCALES_MAX] = {0}; 9869 int g823_mask_exceed[BCM_PTP_CTDEV_NUM_TIMESCALES_MAX] = {0}; 9870 char uint64_decimal_string[27]; 9871 9872 for (i = 0; i < ctdev_alarm_data->num_tau; ++i) { 9873 /* ITU-T G.823 SEC TDEV mask criteria. */ 9874 g823_mask_psec[i] = _bcm_ptp_ctdev_g823_mask(ctdev_alarm_data->tau_sec[i]); 9875 if (COMPILER_64_HI(ctdev_alarm_data->tdev_psec[i]) || 9876 COMPILER_64_LO(ctdev_alarm_data->tdev_psec[i]) > g823_mask_psec[i]) { 9877 g823_mask_exceed[i] = 1; 9878 } 9879 } 9880 9881 /* 9882 * Display formatted C-TDEV(tau) and pass/fail classification based on 9883 * ITU-T G.823 SEC TDEV mask. 9884 */ 9885 cli_out("C-TDEV psec @T=%u: ", (unsigned)sal_time()); 9886 for(i = 0; i < 11; ++i) { 9887 format_uint64_decimal(uint64_decimal_string, ctdev_alarm_data->tdev_psec[i], ','); 9888 cli_out("| (%d) %s - %s ", ctdev_alarm_data->tau_sec[i], uint64_decimal_string, g823_mask_exceed[i] ? "F":"P"); 9889 } 9890 cli_out("\n"); 9891 9892 return BCM_E_NONE; 9893 } 9894 9895 9896 /* 9897 * Function: 9898 * diag_tdpll_input_clock_monitor_callback() 9899 * Purpose: 9900 * T-DPLL input clock monitoring callback example. 9901 * Parameters: 9902 * unit - (IN) Unit number. 9903 * stack_id - (IN) Stack identifier index. 9904 * clock_num - (IN) PTP clock number. 9905 * cb_data - (IN) Input clock monitor callback data. 9906 * Returns: 9907 * BCM_E_XXX - Function status. 9908 * Notes: 9909 */ 9910 STATIC int 9911 diag_tdpll_input_clock_monitor_callback( 9912 int unit, 9913 int stack_id, 9914 bcm_tdpll_input_clock_monitor_cb_data_t *cb_data) 9915 { 9916 cli_out("T-DPLL Input Clock Monitoring Event\n"); 9917 cli_out("Unit: %d Stack: %d\n", unit, stack_id); 9918 cli_out("-----------------------------------------------------------" 9919 "---------------------\n"); 9920 cli_out("Index : %d\n", cb_data->index); 9921 cli_out("Event : <%s> %s\n", 9922 cb_data->monitor_value ? "SET":"CLEAR", 9923 cb_data->monitor_type == bcm_tdpll_input_clock_monitor_type_soft_warn ? 9924 "Over Soft-Warn" : 9925 (cb_data->monitor_type == bcm_tdpll_input_clock_monitor_type_hard_accept ? 9926 "Under Hard-Accept" : 9927 (cb_data->monitor_type == bcm_tdpll_input_clock_monitor_type_hard_reject ? 9928 "Over Hard-Reject":"Unknown"))); 9929 cli_out("\n"); 9930 9931 return BCM_E_NONE; 9932 } 9933 9934 /* 9935 * Function: 9936 * diag_tdpll_input_clock_selector_callback() 9937 * Purpose: 9938 * T-DPLL input clock reference selection callback example. 9939 * Parameters: 9940 * unit - (IN) Unit number. 9941 * stack_id - (IN) Stack identifier index. 9942 * cb_data - (IN) Input clock reference selection callback data. 9943 * Returns: 9944 * BCM_E_XXX - Function status. 9945 * Notes: 9946 */ 9947 STATIC int 9948 diag_tdpll_input_clock_selector_callback( 9949 int unit, 9950 int stack_id, 9951 bcm_tdpll_input_clock_selector_cb_data_t *cb_data) 9952 { 9953 cli_out("T-DPLL Reference Selection Event\n"); 9954 cli_out("Unit: %d Stack: %d\n", unit, stack_id); 9955 cli_out("-----------------------------------------------------------" 9956 "---------------------\n"); 9957 cli_out("DPLL : %d\n", cb_data->dpll_index); 9958 cli_out("Ref. : %d (%d)\n", cb_data->selected_clock, cb_data->prior_selected_clock); 9959 cli_out("\n"); 9960 9961 return BCM_E_NONE; 9962 } 9963 9964 /* 9965 * Function: 9966 * diag_tdpll_input_clock_notification_callback() 9967 * Purpose: 9968 * T-DPLL input clock notification callback example. 9969 * Parameters: 9970 * unit - (IN) Unit number. 9971 * stack_id - (IN) Stack identifier index. 9972 * cb_data - (IN) Input clock callback data. 9973 * Returns: 9974 * BCM_E_XXX - Function status. 9975 * Notes: 9976 */ 9977 STATIC int 9978 diag_tdpll_input_clock_notification_callback( 9979 int unit, 9980 int stack_id, 9981 void *cb_data) 9982 { 9983 9984 bcm_tdpll_input_clock_ref_change_cb_data_t *noti_cb_data; 9985 noti_cb_data = (bcm_tdpll_input_clock_ref_change_cb_data_t *)cb_data; 9986 9987 cli_out("T-DPLL Input Clock Notification Event\n"); 9988 cli_out("Unit: %d Stack: %d\n", unit, stack_id); 9989 cli_out("-----------------------------------------------------------\n"); 9990 9991 switch (noti_cb_data->noti_type) { 9992 case bcmTdpllNotificationTypeRefchange: 9993 cli_out("Notification event: %s\n", "bcmTdpllNotificationTypeRefchange"); 9994 cli_out("DPLL : %d\n", noti_cb_data->dpll_index); 9995 cli_out("Ref. : %d (%d)\n", noti_cb_data->selected_clock, noti_cb_data->prior_selected_clock); 9996 break; 9997 default: 9998 cli_out("Invalid notification type[%d]\n", noti_cb_data->noti_type); 9999 break; 10000 } 10001 10002 cli_out("\n"); 10003 return BCM_E_NONE; 10004 } 10005 10006 /* 10007 * Function: 10008 * diag_tdpll_input_clock_callback() 10009 * Purpose: 10010 * T-DPLL input clock callback example. 10011 * Parameters: 10012 * unit - (IN) Unit number. 10013 * stack_id - (IN) Stack identifier index. 10014 * cb_data - (IN) Input clock callback data. 10015 * Returns: 10016 * BCM_E_XXX - Function status. 10017 * Notes: 10018 */ 10019 STATIC int 10020 diag_tdpll_input_clock_callback( 10021 int unit, 10022 int stack_id, 10023 bcm_tdpll_input_clock_cb_data_t *cb_data) 10024 { 10025 switch (cb_data->callback_type) { 10026 case bcmTdpllCallbackTypeMonitor: 10027 cli_out("diag_tdpll_input_clock_callback for callback type [bcmTdpllCallbackTypeMonitor] \n"); 10028 diag_tdpll_input_clock_monitor_callback(unit, stack_id, 10029 (bcm_tdpll_input_clock_monitor_cb_data_t *)cb_data->cb_info); 10030 break; 10031 10032 case bcmTdpllCallbackTypeSelector: 10033 cli_out("diag_tdpll_input_clock_callback for callback type [bcmTdpllCallbackTypeSelector] \n"); 10034 diag_tdpll_input_clock_selector_callback(unit, stack_id, 10035 (bcm_tdpll_input_clock_selector_cb_data_t *)cb_data->cb_info); 10036 break; 10037 10038 case bcmTdpllCallbackTypeNotification: 10039 cli_out("diag_tdpll_input_clock_callback for callback type [bcmTdpllCallbackTypeNotification] \n"); 10040 diag_tdpll_input_clock_notification_callback(unit, stack_id, cb_data->cb_info); 10041 break; 10042 10043 default: 10044 cli_out("diag_tdpll_input_clock_callback for invalid callback type [%d] \n", cb_data->callback_type); 10045 break; 10046 } 10047 10048 return BCM_E_NONE; 10049 } 10050 10051 /* 10052 * Function: 10053 * diag_tdpll_input_clock_ql_change_callback() 10054 * Purpose: 10055 * ESMC Ql change for input clock reference callback example. 10056 * Parameters: 10057 * unit - (IN) Unit number. 10058 * stack_id - (IN) Stack identifier index. 10059 * cb_data - (IN) Input clock ESMC QL callback data. 10060 * Returns: 10061 * BCM_E_XXX - Function status. 10062 * Notes: 10063 */ 10064 STATIC int 10065 diag_tdpll_input_clock_ql_change_callback( 10066 int unit, 10067 int stack_id, 10068 bcm_tdpll_input_clock_ql_change_cb_data_t *cb_data) 10069 { 10070 cli_out("ESMC QL Change\n"); 10071 cli_out("Unit: %d Stack: %d\n", unit, stack_id); 10072 cli_out("-----------------------------------------------------------" 10073 "---------------------\n"); 10074 cli_out("input_clk_index : %d\n", cb_data->input_clk_index); 10075 cli_out("QL : %d (%d)\n", cb_data->current_ql, cb_data->prior_ql); 10076 cli_out("\n"); 10077 /* Simple implementation of Store the state change in DB */ 10078 /* Recommended to use Queue for communication between threads */ 10079 ql_change_data.input_clk_index = cb_data->input_clk_index; 10080 ql_change_data.current_ql = cb_data->current_ql; 10081 ql_change_data.prior_ql = cb_data->prior_ql; 10082 10083 if (ql_change_data.current_ql != ql_change_data.prior_ql) { 10084 bcm_esmc_network_option_t network_option; 10085 bcm_esmc_g781_option_get(0, 0, &network_option); 10086 if (network_option == bcm_esmc_network_option_g781_I) { 10087 cli_out("Network Option : %d\n", network_option); 10088 if (ql_change_data.current_ql >= bcm_esmc_g781_I_ql_sec) { 10089 cli_out("Disable the Clock : %d\n", ql_change_data.input_clk_index); 10090 sal_dpc((sal_dpc_fn_t)bcm_tdpll_input_clock_enable_set, 10091 INT_TO_PTR(unit), 10092 INT_TO_PTR(stack_id), 10093 INT_TO_PTR(ql_change_data.input_clk_index), 10094 INT_TO_PTR(FALSE), 0); 10095 } else { 10096 cli_out("Enable the Clock : %d\n", ql_change_data.input_clk_index); 10097 sal_dpc((sal_dpc_fn_t)bcm_tdpll_input_clock_enable_set, 10098 INT_TO_PTR(unit), 10099 INT_TO_PTR(stack_id), 10100 INT_TO_PTR(ql_change_data.input_clk_index), 10101 INT_TO_PTR(TRUE), 0); 10102 } 10103 } 10104 ql_change_data.prior_ql = ql_change_data.current_ql; 10105 } 10106 10107 return BCM_E_NONE; 10108 10109 } 10110 10111 /* 10112 * Function: 10113 * diag_port_state_description 10114 * Purpose: 10115 * Interpret PTP port state values. 10116 * Parameters: 10117 * state - (IN) PTP port state code. 10118 * Returns: 10119 * Port state description 10120 * Notes: 10121 * Ref. IEEE Std. 1588-2008, Chapter 8.2.5.3.1, Table 8. 10122 */ 10123 STATIC const char* 10124 diag_port_state_description(_bcm_ptp_port_state_t state) 10125 { 10126 switch(state) { 10127 case _bcm_ptp_state_initializing: 10128 return "Init"; 10129 10130 case _bcm_ptp_state_faulty: 10131 return "Faulty"; 10132 10133 case _bcm_ptp_state_disabled: 10134 return "Disabled"; 10135 10136 case _bcm_ptp_state_listening: 10137 return "Listening"; 10138 10139 case _bcm_ptp_state_pre_master: 10140 return "Pre-Master"; 10141 10142 case _bcm_ptp_state_master: 10143 return "Master"; 10144 10145 case _bcm_ptp_state_passive: 10146 return "Passive"; 10147 10148 case _bcm_ptp_state_uncalibrated: 10149 return "Uncalibrated"; 10150 10151 case _bcm_ptp_state_slave: 10152 return "Slave"; 10153 10154 default: 10155 return "<invalid>"; 10156 } 10157 } 10158 10159 /* 10160 * Function: 10161 * diag_ieee1588_warn_reason_description 10162 * Purpose: 10163 * Interpret IEEE Std. 1588-2008 warning values. 10164 * Parameters: 10165 * reason - (IN) IEEE Std. 1588-2008 warning code. 10166 * Returns: 10167 * Warning reason. 10168 * Notes: 10169 * Function provides an implementation specific set of warnings 10170 * relevant to the IEEE Std. 1588-2008. 10171 */ 10172 STATIC const char* 10173 diag_ieee1588_warn_reason_description( 10174 _bcm_ptp_ieee1588_warn_reason_t reason) 10175 { 10176 switch(reason) { 10177 case _bcm_ptp_ieee1588_warn_reason_logAnnounceInterval: 10178 return "Non-uniform logAnnounceInterval in PTP domain"; 10179 10180 default: 10181 return "<invalid>"; 10182 } 10183 } 10184 10185 /* 10186 * Function: 10187 * diag_servo_state_description 10188 * Purpose: 10189 * Interpret servo state values. 10190 * Parameters: 10191 * state - (IN) Servo state code. 10192 * Returns: 10193 * Servo state description 10194 * Notes: 10195 */ 10196 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 10197 STATIC const char* 10198 diag_servo_state_description( 10199 int state) 10200 { 10201 switch (state) { 10202 case bcmPtpServoStateAcquiring: 10203 return "Acquiring Lock"; 10204 10205 case bcmPtpServoStateWarmup: 10206 return "Warmup"; 10207 10208 case bcmPtpServoStateFastLoop: 10209 return "Fast Loop"; 10210 10211 case bcmPtpServoStateNormal: 10212 return "Normal Loop"; 10213 10214 case bcmPtpServoStateBridge: 10215 return "Bridge"; 10216 10217 case bcmPtpServoStateHoldover: 10218 return "Holdover"; 10219 10220 case bcmPtpServoStateInitial: 10221 return "Initial"; 10222 10223 case bcmPtpServoStateUnqualified: 10224 return "Unqualified"; 10225 10226 case bcmPtpServoStateFreqLocked: 10227 return "Frequency Locked"; 10228 10229 case bcmPtpServoStateTimeLocked: 10230 return "Time Locked"; 10231 10232 case bcmPtpServoStateHoldoverInSpec: 10233 return "Holdover-in-spec"; 10234 10235 case bcmPtpServoStateHoldoverOutOfSpec: 10236 return "Holdover-out-of-spec"; 10237 10238 case bcmPtpServoStateFreerun: 10239 return "Free run"; 10240 10241 default: 10242 return "<Unknown>"; 10243 } 10244 } 10245 10246 #else 10247 STATIC const char* 10248 diag_servo_state_description( 10249 bcm_ptp_fll_state_t state) 10250 { 10251 switch (state) { 10252 case bcmPTPFLLStateAcquiring: 10253 return "Acquiring Lock"; 10254 10255 case bcmPTPFLLStateWarmup: 10256 return "Warmup"; 10257 10258 case bcmPTPFLLStateFastLoop: 10259 return "Fast Loop"; 10260 10261 case bcmPTPFLLStateNormal: 10262 return "Normal Loop"; 10263 10264 case bcmPTPFLLStateBridge: 10265 return "Bridge"; 10266 10267 case bcmPTPFLLStateHoldover: 10268 return "Holdover"; 10269 10270 default: 10271 return "<Unknown>"; 10272 } 10273 } 10274 #endif 10275 10276 /* 10277 * Function: 10278 * diag_servo_lock_status_description 10279 * Purpose: 10280 * Interpret servo lock status values. 10281 * Parameters: 10282 * state - (IN) Servo lock status code. 10283 * Returns: 10284 * Servo lock status description 10285 * Notes: 10286 */ 10287 STATIC const char* 10288 diag_servo_lock_status_description( 10289 bcm_ptp_servo_lock_status_t state) 10290 { 10291 switch (state) { 10292 case bcmPTPServoStatusUnlocked: 10293 return "Unlocked"; 10294 10295 case bcmPTPServoStatusFreqLocked: 10296 return "Frequency Locked"; 10297 10298 case bcmPTPServoStatusPhaseLocked: 10299 return "Phase Locked"; 10300 10301 case bcmPTPServoStatusFreqPhaseLocked: 10302 return "Freq-Phase Locked"; 10303 10304 default: 10305 return "<Unknown>"; 10306 } 10307 } 10308 10309 /* 10310 * Function: 10311 * diag_pps_in_state_description 10312 * Purpose: 10313 * Interpret PPS-in state values. 10314 * Parameters: 10315 * state - (IN) PPS-in state code. 10316 * Returns: 10317 * PPS-in state description 10318 * Notes: 10319 */ 10320 STATIC const char* 10321 diag_pps_in_state_description( 10322 _bcm_ptp_pps_in_state_t state) 10323 { 10324 switch (state) { 10325 case _bcm_ptp_pps_in_state_missing: 10326 return "No PPS IN"; 10327 10328 case _bcm_ptp_pps_in_state_active_missing_tod: 10329 return "PPS IN, but no valid ToD"; 10330 10331 case _bcm_ptp_pps_in_state_valid: 10332 return "PPS IN with valid ToD"; 10333 10334 default: 10335 return "<Unknown>"; 10336 } 10337 } 10338 10339 /* 10340 * Function: 10341 * diag_telecom_QL_description 10342 * Purpose: 10343 * Interpret telecom profile QL values. 10344 * Parameters: 10345 * QL - (IN) Telecom profile quality level (QL) value. 10346 * Returns: 10347 * ITU-T G.781 QL description. 10348 * Notes: 10349 */ 10350 STATIC const char* 10351 diag_telecom_QL_description( 10352 const bcm_ptp_telecom_g8265_quality_level_t QL) 10353 { 10354 switch (QL) { 10355 case bcm_ptp_telecom_g8265_ql_I_prc: 10356 return "QL-PRC"; 10357 case bcm_ptp_telecom_g8265_ql_I_ssua: 10358 return "QL-SSU-A"; 10359 case bcm_ptp_telecom_g8265_ql_I_ssub: 10360 return "QL-SSU-B"; 10361 case bcm_ptp_telecom_g8265_ql_I_sec: 10362 return "QL-SEC"; 10363 case bcm_ptp_telecom_g8265_ql_I_dnu: 10364 return "QL-DNU"; 10365 case bcm_ptp_telecom_g8265_ql_II_prs: 10366 return "QL-PRS"; 10367 case bcm_ptp_telecom_g8265_ql_II_stu: 10368 return "QL-STU"; 10369 case bcm_ptp_telecom_g8265_ql_II_st2: 10370 return "QL-ST2"; 10371 case bcm_ptp_telecom_g8265_ql_II_tnc: 10372 return "QL-TNC"; 10373 case bcm_ptp_telecom_g8265_ql_II_st3e: 10374 return "QL-ST3E"; 10375 case bcm_ptp_telecom_g8265_ql_II_st3: 10376 return "QL-ST3"; 10377 case bcm_ptp_telecom_g8265_ql_II_smc: 10378 return "QL-SMC"; 10379 case bcm_ptp_telecom_g8265_ql_II_prov: 10380 return "QL-PROV"; 10381 case bcm_ptp_telecom_g8265_ql_II_dus: 10382 return "QL-DUS"; 10383 case bcm_ptp_telecom_g8265_ql_III_unk: 10384 return "QL-UNK"; 10385 case bcm_ptp_telecom_g8265_ql_III_sec: 10386 return "QL-SEC"; 10387 case bcm_ptp_telecom_g8265_ql_na_slv: 10388 return "N/A"; 10389 default: 10390 return "<Invalid>"; 10391 } 10392 } 10393 10394 /* 10395 * Function: 10396 * diag_telecom_pktmaster_state_description 10397 * Purpose: 10398 * Interpret telecom profile packet master state. 10399 * Parameters: 10400 * state - (IN) Telecom profile packet master state. 10401 * Returns: 10402 * Packet master state description. 10403 * Notes: 10404 */ 10405 STATIC const char* 10406 diag_telecom_pktmaster_state_description( 10407 const bcm_ptp_telecom_g8265_pktmaster_state_t state) 10408 { 10409 switch (state) { 10410 case bcm_ptp_telecom_g8265_pktmaster_state_unused: 10411 return "Unused"; 10412 case bcm_ptp_telecom_g8265_pktmaster_state_init: 10413 return "Initialized"; 10414 case bcm_ptp_telecom_g8265_pktmaster_state_valid: 10415 return "Valid"; 10416 default: 10417 return "<Invalid>"; 10418 } 10419 } 10420 10421 /* 10422 * Function: 10423 * diag_telecom_pktmaster_printout 10424 * Purpose: 10425 * Print telecom profile packet master attributes. 10426 * Parameters: 10427 * pktmaster - (IN) Telecom profile packet master. 10428 * flags - (IN) Printout control flags. 10429 * Returns: 10430 * None. 10431 * Notes: 10432 */ 10433 STATIC void 10434 diag_telecom_pktmaster_printout( 10435 bcm_ptp_telecom_g8265_pktmaster_t *pktmaster, 10436 uint8 flags) 10437 { 10438 sal_time_t dt, dt_p, dt_q; 10439 sal_time_t t = _bcm_ptp_monotonic_time(); 10440 uint64 t64; 10441 10442 if (bcmPTPUDPIPv4 == pktmaster->port_address.addr_type) { 10443 cli_out("IP (IPv4) : %u.%u.%u.%u\n", 10444 pktmaster->port_address.address[0], pktmaster->port_address.address[1], 10445 pktmaster->port_address.address[2], pktmaster->port_address.address[3]); 10446 } else if (bcmPTPUDPIPv6 == pktmaster->port_address.addr_type) { 10447 cli_out("IP (IPv6) : %02x%02x:%02x%02x:%02x%02x:%02x%02x:" 10448 "%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", 10449 pktmaster->port_address.address[0], pktmaster->port_address.address[1], 10450 pktmaster->port_address.address[2], pktmaster->port_address.address[3], 10451 pktmaster->port_address.address[4], pktmaster->port_address.address[5], 10452 pktmaster->port_address.address[6], pktmaster->port_address.address[7], 10453 pktmaster->port_address.address[8], pktmaster->port_address.address[9], 10454 pktmaster->port_address.address[10], pktmaster->port_address.address[11], 10455 pktmaster->port_address.address[12], pktmaster->port_address.address[13], 10456 pktmaster->port_address.address[14], pktmaster->port_address.address[15]); 10457 } 10458 10459 if (0 == flags) { 10460 return; 10461 } 10462 10463 cli_out("portIdentity : %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%04x\n", 10464 pktmaster->port_identity.clock_identity[0], pktmaster->port_identity.clock_identity[1], 10465 pktmaster->port_identity.clock_identity[2], pktmaster->port_identity.clock_identity[3], 10466 pktmaster->port_identity.clock_identity[4], pktmaster->port_identity.clock_identity[5], 10467 pktmaster->port_identity.clock_identity[6], pktmaster->port_identity.clock_identity[7], 10468 pktmaster->port_identity.port_number); 10469 10470 cli_out("\n"); 10471 cli_out("State : %s\n", 10472 diag_telecom_pktmaster_state_description(pktmaster->state)); 10473 10474 cli_out("\n"); 10475 cli_out("ITU-T G.781 QL : %s\n", diag_telecom_QL_description(pktmaster->quality_level)); 10476 cli_out("Priority : %u\n", pktmaster->priority.value); 10477 if (pktmaster->priority.override) { 10478 cli_out(" Override : [x]\n"); 10479 } else { 10480 cli_out(" Override : [ ]\n"); 10481 } 10482 cli_out(" GM priority1 : %u\n", pktmaster->grandmaster_priority1); 10483 cli_out(" GM priority2 : %u\n", pktmaster->grandmaster_priority2); 10484 10485 cli_out("\n"); 10486 if (pktmaster->selector.lockout) { 10487 cli_out("Lockout : [x]\n"); 10488 } else { 10489 cli_out("Lockout : [ ]\n"); 10490 } 10491 if (pktmaster->selector.non_reversion) { 10492 cli_out("Non-Reversion : [x]\n"); 10493 } else { 10494 cli_out("Non-Reversion : [ ]\n"); 10495 } 10496 if (pktmaster->selector.wait_to_restore) { 10497 if (pktmaster->selector.non_reversion) { 10498 cli_out("Wait-to-Restore : [x] (Inf. sec)\n"); 10499 } else { 10500 COMPILER_64_SET(t64, 0, t); 10501 COMPILER_64_SUB_64(t64, pktmaster->ptsf.timestamp); 10502 if(COMPILER_64_LT(t64, pktmaster->selector.wait_sec)){ 10503 t64 = pktmaster->ptsf.timestamp; 10504 COMPILER_64_ADD_64(t64, pktmaster->selector.wait_sec); 10505 COMPILER_64_SUB_32(t64, t); 10506 dt_p = COMPILER_64_LO(t64); 10507 } else { 10508 dt_p = 0; 10509 } 10510 COMPILER_64_SET(t64, 0, t); 10511 COMPILER_64_SUB_64(t64, pktmaster->hql.timestamp); 10512 if(COMPILER_64_LT(t64, pktmaster->selector.wait_sec)){ 10513 t64 = pktmaster->hql.timestamp; 10514 COMPILER_64_ADD_64(t64, pktmaster->selector.wait_sec); 10515 COMPILER_64_SUB_32(t64, t); 10516 dt_q = COMPILER_64_LO(t64); 10517 } else { 10518 dt_q = 0; 10519 } 10520 dt = (dt_p > dt_q) ? (dt_p):(dt_q); 10521 cli_out("Wait-to-Restore : [x] (%u sec)\n", (uint32)dt); 10522 } 10523 } else { 10524 cli_out("Wait-to-Restore : [ ]\n"); 10525 } 10526 10527 cli_out("\n"); 10528 if (pktmaster->ptsf.loss_announce || pktmaster->ptsf.loss_sync || 10529 pktmaster->ptsf.unusable) { 10530 cli_out("PTSF : [x]\n"); 10531 } else { 10532 cli_out("PTSF : [ ]\n"); 10533 } 10534 if (pktmaster->ptsf.loss_announce) { 10535 cli_out(" : [x]lossAnnounce "); 10536 } else { 10537 cli_out(" : [ ]lossAnnounce "); 10538 } 10539 if (pktmaster->ptsf.loss_sync) { 10540 cli_out("[x]lossSync "); 10541 } else { 10542 cli_out("[ ]lossSync "); 10543 } 10544 if (pktmaster->ptsf.unusable) { 10545 cli_out("[x]unusable\n"); 10546 } else { 10547 cli_out("[ ]unusable\n"); 10548 } 10549 if (pktmaster->ptsf.loss_timing_sync) { 10550 cli_out(" : [x]lossTimingSync "); 10551 } else { 10552 cli_out(" : [ ]lossTimingSync "); 10553 } 10554 if (pktmaster->ptsf.loss_timing_sync_ts) { 10555 cli_out("[x]lossTimingSyncTS "); 10556 } else { 10557 cli_out("[ ]lossTimingSyncTS "); 10558 } 10559 if (pktmaster->ptsf.loss_timing_delay) { 10560 cli_out("[x]lossTimingDelay\n"); 10561 } else { 10562 cli_out("[ ]lossTimingDelay\n"); 10563 } 10564 10565 cli_out("\n"); 10566 if (pktmaster->hql.degrade_ql) { 10567 cli_out("QL Degraded : [x]\n"); 10568 } else { 10569 cli_out("QL Degraded : [ ]\n"); 10570 } 10571 10572 #ifdef COMPILER_HAS_LONGLONG 10573 cli_out("\n"); 10574 if (COMPILER_64_LO(pktmaster->pktstats.pdv_scaled_allan_var) == ((uint32)-1) && 10575 COMPILER_64_HI(pktmaster->pktstats.pdv_scaled_allan_var) == ((uint32)-1)) { 10576 cli_out("MTSD Scaled AVAR: N/A\n"); 10577 } else { 10578 cli_out("MTSD Scaled AVAR: %llu (nsec-sq)\n", 10579 (long long unsigned)pktmaster->pktstats.pdv_scaled_allan_var); 10580 } 10581 #endif /* COMPILER_HAS_LONGLONG */ 10582 } 10583 10584 10585 #endif /* __KERNEL__ */ 10586 10587 #if defined(PTP_KEYSTONE_STACK) 10588 10589 #ifndef NO_FILEIO 10590 10591 uint32 ptp_ks_ihex_ext_addr; /* Extended Address */ 10592 10593 /* 10594 * returs -1 if error 10595 * returns number of bytes. (0 if this record doesn't contain any data). 10596 */ 10597 STATIC int 10598 ptp_parse_ihex_record(int unit, char *line, uint32 *off) 10599 { 10600 int count; 10601 uint32 address; 10602 10603 switch (line[8]) { /* Record Type */ 10604 case '0' : /* Data Record */ 10605 count = (xdigit2i(line[1]) << 4) | 10606 (xdigit2i(line[2])); 10607 10608 address = (xdigit2i(line[3]) << 12) | 10609 (xdigit2i(line[4]) << 8) | 10610 (xdigit2i(line[5]) << 4) | 10611 (xdigit2i(line[6])); 10612 10613 *off = ptp_ks_ihex_ext_addr + address; 10614 return count; 10615 break; /* Not Reachable */ 10616 case '4' : /* Extended Linear Address Record */ 10617 address = (xdigit2i(line[9]) << 12) | 10618 (xdigit2i(line[10]) << 8) | 10619 (xdigit2i(line[11]) << 4) | 10620 (xdigit2i(line[12])); 10621 10622 ptp_ks_ihex_ext_addr = (address << 16); 10623 cli_out("Exteded Linear Address 0x%x\n", ptp_ks_ihex_ext_addr); 10624 return 0; 10625 break; /* Not Reachable */ 10626 default : /* We don't parse all other records */ 10627 cli_out("Unsupported Record\n"); 10628 return 0; 10629 } 10630 return -1; /* Why are we here? */ /* Not Reachable */ 10631 } 10632 10633 STATIC int 10634 ptp_parse_srec_record (int unit, char *line, uint32 *off) 10635 { 10636 int count; 10637 uint32 address; 10638 10639 switch (line[1]) { /* Record Type */ 10640 case '0': /* Header record - ignore */ 10641 return 0; 10642 break; /* Not Reachable */ 10643 10644 case '1' : /* Data Record with 2 byte address */ 10645 count = (xdigit2i(line[2]) << 4) | 10646 (xdigit2i(line[3])); 10647 count -= 3; /* 2 address + 1 checksum */ 10648 10649 address = (xdigit2i(line[4]) << 12) | 10650 (xdigit2i(line[5]) << 8) | 10651 (xdigit2i(line[6]) << 4) | 10652 (xdigit2i(line[7])); 10653 10654 *off = address; 10655 return count; 10656 break; /* Not Reachable */ 10657 10658 case '2' : /* Data Record with 3 byte address */ 10659 count = (xdigit2i(line[2]) << 4) | 10660 (xdigit2i(line[3])); 10661 count -= 4; /* 3 address + 1 checksum */ 10662 10663 address = (xdigit2i(line[4]) << 20) | 10664 (xdigit2i(line[5]) << 16) | 10665 (xdigit2i(line[6]) << 12) | 10666 (xdigit2i(line[7]) << 8) | 10667 (xdigit2i(line[8]) << 4) | 10668 (xdigit2i(line[9])); 10669 10670 *off = address; 10671 return count; 10672 break; /* Not Reachable */ 10673 10674 case '3' : /* Data Record with 4 byte address */ 10675 count = (xdigit2i(line[2]) << 4) | 10676 (xdigit2i(line[3])); 10677 count -= 5; /* 4 address + 1 checksum */ 10678 10679 address = (xdigit2i(line[4]) << 28) | 10680 (xdigit2i(line[5]) << 24) | 10681 (xdigit2i(line[6]) << 20) | 10682 (xdigit2i(line[7]) << 16) | 10683 (xdigit2i(line[8]) << 12) | 10684 (xdigit2i(line[9]) << 8) | 10685 (xdigit2i(line[10]) << 4) | 10686 (xdigit2i(line[11])); 10687 10688 *off = address; 10689 return count; 10690 break; /* Not Reachable */ 10691 10692 case '5': /* Record count - ignore */ 10693 case '6': /* End of block - ignore */ 10694 case '7': /* End of block - ignore */ 10695 case '8': /* End of block - ignore */ 10696 case '9': /* End of block - ignore */ 10697 return 0; 10698 break; /* Not Reachable */ 10699 10700 default : /* We don't parse all other records */ 10701 cli_out("Unsupported Record S%c\n", line[1]); 10702 return 0; 10703 } 10704 return -1; /* Why are we here? */ /* Not Reachable */ 10705 } 10706 10707 10708 /* 10709 * It is assumed that by the time this routine is called 10710 * the record is already validated. So, blindly get data 10711 */ 10712 STATIC void 10713 ptp_get_rec_data (char *line, int count, uint8 *dat) 10714 { 10715 int i, datpos = 9; /* 9 is valid for ihex */ 10716 10717 if (!count) { 10718 return; 10719 } 10720 10721 if (line[0] != ':') { 10722 /* not ihex */ 10723 switch (line[1]) { 10724 case '1': /* S1 record */ 10725 datpos = 8; 10726 break; 10727 case '2': /* S2 record */ 10728 datpos = 10; 10729 break; 10730 case '3': /* S3 record */ 10731 datpos = 12; 10732 break; 10733 default: 10734 cli_out("Unexpected record type: '%c'\n", line[1]); 10735 break; 10736 } 10737 } 10738 10739 /*1 count = 2 hex chars */ 10740 for(i = 0; i < count; i++) { 10741 *(dat + i) = ((xdigit2i(line[datpos + (i * 2)])) << 4) | 10742 (xdigit2i(line[datpos + (i * 2) + 1])); 10743 } 10744 } 10745 10746 STATIC cmd_result_t 10747 ptp_file_load(int unit, FILE *fp, int ksnum) { 10748 uint32 addr=0; 10749 int rv = 0; 10750 char input[256], *cp = NULL; 10751 unsigned char data[256]; 10752 uint32 phys_addr; 10753 10754 ptp_ks_ihex_ext_addr = 0; /* Until an extended addr record is met.. */ 10755 10756 while (NULL != (cp = fgets(input, sizeof(input) - 1, fp))) { 10757 if (input[0] == 'S') { 10758 rv = ptp_parse_srec_record(unit, cp, &addr); 10759 } else if (input[0] == ':') { 10760 rv = ptp_parse_ihex_record(unit, cp, &addr); 10761 } else { 10762 cli_out("unknown Record Type\n"); 10763 rv = -1; 10764 } 10765 10766 if (-1 == rv) { 10767 return (CMD_FAIL); 10768 } 10769 10770 if (rv % 4) { 10771 cli_out("record Not Multiple of 4\n"); 10772 return (CMD_FAIL); 10773 } 10774 ptp_get_rec_data (cp, rv, data); 10775 10776 /* for BCM53903, physical memory has top two addr bits == 0 */ 10777 /* virt addr depends on cached status */ 10778 10779 phys_addr = (addr & 0x1fffffff); 10780 _bcm_ptp_write_pcishared_uint8_aligned_array(ksnum, phys_addr, data, rv); 10781 } 10782 10783 return(CMD_OK); 10784 } 10785 10786 10787 STATIC cmd_result_t 10788 ptp_file_load_bin(int unit, FILE *fp, int ksnum) { 10789 uint32 addr = 0x19000000; /* base physical RAM address */ 10790 unsigned char data[256]; 10791 unsigned data_len; 10792 10793 while (0 != (data_len = (unsigned) fread(data, 1, 256, fp))) { 10794 _bcm_ptp_write_pcishared_uint8_aligned_array(ksnum, addr, data, data_len); 10795 addr += data_len; 10796 } 10797 10798 return(CMD_OK); 10799 } 10800 10801 #endif 10802 10803 10804 char cmd_topload_usage[] = 10805 "Parameters: <ksnum> <file.srec>\n\t\t" 10806 #ifndef COMPILER_STRING_CONST_LIMIT 10807 "Load the MCS memory area from <file.srec>.\n\t" 10808 "ksnum = BCM53903 number to be loaded.\n" 10809 #endif 10810 ; 10811 10812 cmd_result_t 10813 cmd_topload(int unit, args_t *a) 10814 /* 10815 * Function: cmd_topload 10816 * Purpose: Load a file into ToP processor for 1588 10817 * Parameters: unit - unit 10818 * a - args, each of the files to be displayed. 10819 * Returns: CMD_OK/CMD_FAIL/CMD_USAGE 10820 */ 10821 { 10822 cmd_result_t rv = CMD_OK; 10823 char *c , *filename; 10824 int ksnum; 10825 10826 #ifndef NO_FILEIO 10827 int resetks = 1; /* reset the TOP before loading */ 10828 int startks = 0; /* don't start TOP after load: let stack start do that */ 10829 10830 #ifndef NO_CTRL_C 10831 jmp_buf ctrl_c; 10832 #endif 10833 FILE * volatile fp = NULL; 10834 #endif 10835 10836 if (ARG_CNT(a) < 2) { 10837 return(CMD_USAGE); 10838 } 10839 10840 c = ARG_GET(a); 10841 if (!isint(c)) { 10842 cli_out("%s: Error: BCM53903 number not specified\n", ARG_CMD(a)); 10843 return(CMD_USAGE); 10844 } 10845 10846 ksnum = parse_integer(c); 10847 if (ksnum > 1) { 10848 cli_out("Invalid uProcessor number: %d\n",ksnum); 10849 return(CMD_FAIL); 10850 } 10851 10852 10853 c = ARG_GET(a); 10854 filename = c; 10855 if (filename == NULL) { 10856 cli_out("%s: Error: No file specified\n", ARG_CMD(a)); 10857 return(CMD_USAGE); 10858 } 10859 10860 #ifdef NO_FILEIO 10861 cli_out("no filesystem\n"); 10862 #else 10863 #ifndef NO_CTRL_C 10864 if (!setjmp(ctrl_c)) { 10865 sh_push_ctrl_c(&ctrl_c); 10866 #endif 10867 10868 /* Reset the ToP before load */ 10869 if (resetks) { 10870 _bcm_ptp_ext_stack_reset(ksnum); 10871 } 10872 10873 fp = sal_fopen(filename, "r"); 10874 if (!fp) { 10875 cli_out("%s: Error: Unable to open file: %s\n", 10876 ARG_CMD(a), filename); 10877 rv = CMD_FAIL; 10878 #ifndef NO_CTRL_C 10879 sh_pop_ctrl_c(); 10880 #endif 10881 return(rv); 10882 } else { 10883 if (sal_strlen(filename) > 4 && 10884 sal_strcmp(filename + sal_strlen(filename) - 4, ".bin") == 0) { 10885 rv = ptp_file_load_bin(unit, fp, ksnum); 10886 } else { 10887 /* interpret as srec / ihex depending on file contents */ 10888 rv = ptp_file_load(unit, fp, ksnum); 10889 } 10890 sal_fclose((FILE *)fp); 10891 fp = NULL; 10892 } 10893 10894 if (startks) { 10895 _bcm_ptp_ext_stack_start(ksnum); 10896 } 10897 10898 #ifndef NO_CTRL_C 10899 } else if (fp) { 10900 sal_fclose((FILE *)fp); 10901 fp = NULL; 10902 rv = CMD_INTR; 10903 } 10904 10905 sh_pop_ctrl_c(); 10906 #endif 10907 #endif /* NO_FILEIO */ 10908 sal_usleep(10000); 10909 10910 return(rv); 10911 } 10912 10913 char cmd_topinfo_usage[] = 10914 "Print information about ToP Firmware\n"; 10915 10916 cmd_result_t 10917 cmd_topinfo(int unit, args_t *a) 10918 /* 10919 * Function: cmd_topinfo 10920 * Purpose: Get information about TOP FW 10921 * Returns: CMD_OK/CMD_FAIL/CMD_USAGE 10922 */ 10923 { 10924 _bcm_ptp_ext_fw_info_t info; 10925 uint32 boot_status, fault_status; 10926 10927 _bcm_ptp_ext_fw_info_get(unit, 0, &info); 10928 _bcm_ptp_ext_stack_fault_status_get(0, &boot_status, &fault_status); 10929 10930 cli_out("--------------------------------------------------------------------------------\n"); 10931 cli_out("PTP Stack Information\n"); 10932 cli_out("--------------------------------------------------------------------------------\n"); 10933 cli_out(" Firmware Version : %s\n", info.firmware_version); 10934 cli_out(" Servo Version : %s\n", info.servo_version); 10935 cli_out("\n"); 10936 cli_out(" PTP Timer Frequency : %u Hz\n", info.ptp_stack_timer_hz); 10937 cli_out("\n"); 10938 cli_out(" Max. # PTP Clocks : %u\n", info.ptp_clocks_max); 10939 cli_out(" Max. # PTP Ports : %u/clock\n", info.ptp_ports_per_clock_max); 10940 cli_out("\n"); 10941 /* cli_out(" Max. # Unicast Masters : %u\n", info.unicast_masters_max); */ 10942 /* cli_out(" Max. # Unicast Slaves : %u\n", info.unicast_slaves_max); */ 10943 cli_out(" Max. # Foreign Master : %u/port\n", info.foreign_master_dataset_entries_max); 10944 cli_out(" Dataset Entries\n"); 10945 cli_out(" Boot Status: %08x Fault Status: %08x\n", boot_status, fault_status); 10946 cli_out("--------------------------------------------------------------------------------\n"); 10947 10948 return CMD_OK; 10949 } 10950 10951 #endif /* defined(PTP_KEYSTONE_STACK) */ 10952 10953 #if defined(BCM_TRIDENT2_SUPPORT) 10954 /* 10955 * Function: 10956 * bcm_esw_ptp_map_input_synce_clock 10957 * Purpose: 10958 * Map PTP input L1 clock from logical port to physical port. 10959 * Parameters: 10960 * logical_l1_clk_port - (IN) Logical PTP input L1 clock port. 10961 * Returns: 10962 * int - Physical PTP input L1 clock port. 10963 * Notes: 10964 */ 10965 int 10966 bcm_esw_ptp_map_input_synce_clock( 10967 int logical_l1_clk_port) 10968 { 10969 int port = 0; 10970 int n = logical_l1_clk_port / 4; 10971 int lane = logical_l1_clk_port % 4; 10972 10973 /************************************************************************************************* 10974 For Trident 2, there are 132 (4 for each 32 TSCs plus 4 LCPLLs) ports on the L1 recovery mux. 10975 The SyncE clocks recovered from the 32 TSCs are multiplexed to the first 128 ports on the mux. 10976 Since these port numbers may not be the same as the front port numbers, an addtional parameter, 10977 BackupTimeInputSynce, is added to the "ptp chan set" command to specify the SyncE input port on 10978 the L1 clock recovery mux. To get the SyncE input port number, user needs to use "phy info" to 10979 indentify the front panel port which carries the input SyncE clock is mapped at lane x (x=0, 1, 10980 2, 3) on TSC n (n= 0, 1, ..., 31). The BackupTimeInputSynce needs to be input with value of 10981 n * 4 + x. 10982 10983 In the current Trident 2 H/W design, the TSC L1_recovery_clock[3:0] is from physical lane instead 10984 of logic port as calculated above and expected by the TD2 top level. To resolve this issue, the 10985 following mapping is added. 10986 10987 For even TSC (TSC0 ...) 10988 i. link_status[3] <-> recovery_clock[3] 10989 ii. link_status[2] <-> recovery_clock[0] 10990 iii. link_status[1] <-> recovery_clock[1] 10991 iv. link_status[0] <-> recovery_clock[2] 10992 For odd TSC (TSC1 ...) 10993 i. Link_status[3] <-> recovery_clock[2] 10994 ii. Link_status[2] <-> recovery_clock[1] 10995 iii. Link_status[1] <-> recovery_clock[0] 10996 iv. Link_status[0] <-> recovery_clock[3] 10997 10998 Note: The above mapping is based on Broadcom Trident 2 SVK. If customer has different board level 10999 design, the mapping needs to be adjusted. 11000 11001 The LCPLLs are multiplexed to ports 128 - 132. No mapping is needed for LCPLLs ports. 11002 */ 11003 if ((logical_l1_clk_port >= 128) && (logical_l1_clk_port <= 131)) 11004 { 11005 return logical_l1_clk_port; 11006 } 11007 11008 if ((n / 2) == 0) 11009 { 11010 /* even TCS */ 11011 if (lane == 0) 11012 port = 2; 11013 else if (lane == 1) 11014 port = 1; 11015 else if (lane == 2) 11016 port = 0; 11017 else if (lane == 3) 11018 port = 3; 11019 } 11020 else 11021 { 11022 /* odd TCS */ 11023 if (lane == 0) 11024 port = 3; 11025 else if (lane == 1) 11026 port = 0; 11027 else if (lane == 2) 11028 port = 1; 11029 else if (lane == 3) 11030 port = 2; 11031 } 11032 11033 return (n * 4 + port); 11034 } 11035 #endif /* BCM_TRIDENT2_SUPPORT */ 11036 11037 #endif /* defined(INCLUDE_PTP) */