openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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, &ethertype, 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, &ethertype, 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, &ethertype, 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) */