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

phy.c (405702B)


      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:        phy.c
      8  * Purpose:     Functions to support CLI port commands
      9  * Requires:    
     10  */
     11 #include <sal/core/libc.h>
     12 #include <sal/types.h>
     13 #include <sal/appl/sal.h>
     14 #include <sal/appl/io.h>
     15 #include <sal/core/libc.h>
     16 #include <shared/bsl.h>
     17 
     18 #include <soc/phy.h>
     19 #include <soc/phy/phymod_sim.h>
     20 #include <soc/eyescan.h>
     21 #include <soc/phy/phyctrl.h>
     22 
     23 #include <appl/diag/shell.h>
     24 #include <appl/diag/system.h>
     25 #include <appl/diag/diag.h>
     26 #include <appl/diag/dport.h>
     27 
     28 #ifdef PHYMOD_LINKCAT_SUPPORT
     29 #include "include/Blackhawk_LinkCAT_lib.h"
     30 #endif /* PHYMOD_LINKCAT_SUPPORT */
     31 
     32 #if defined(BCM_ESW_SUPPORT)
     33 #include <bcm_int/esw/port.h>
     34 #endif
     35 
     36 #if defined(PHYMOD_SUPPORT)
     37 #include <appl/diag/phymod/phymod_symop.h>
     38 #include <soc/phyreg.h>
     39 #include <soc/phy/phymod_ctrl.h>
     40 #include <phymod/phymod_reg.h>
     41 #include <phymod/phymod_debug.h>
     42 #include <phymod/phymod_diag.h>
     43 #if defined(PORTMOD_SUPPORT)
     44 #include <soc/portmod/portmod.h>
     45 #include <soc/portmod/portmod_internal.h>
     46 #endif
     47 #endif
     48 #if defined(PORTMOD_SUPPORT)
     49 #include <soc/portmod/portmod_common.h>
     50 #include <soc/portmod/portmod_chain.h>
     51 #endif
     52 
     53 #ifdef SW_AUTONEG_SUPPORT
     54 #include <bcm_int/common/sw_an.h>
     55 #endif
     56 
     57 #ifdef INCLUDE_PHY_SYM_DBG
     58 /* For timebeing adding the headers for socket calls directly */
     59 #include<sys/types.h>
     60 #include<sys/socket.h>
     61 #include<netinet/in.h>
     62 #include<unistd.h>
     63 #ifdef VXWORKS
     64 #include <vxWorks.h>
     65 #include <sockLib.h>
     66 #include <selectLib.h>
     67 #else
     68 #include<sys/select.h>
     69 #endif
     70 #endif
     71 
     72 #if defined(INCLUDE_PHY_8806X)
     73 #include <phy8806x_funcs.h>
     74 #include <phy8806x_ctr.h>
     75 extern int phy_is_8806x(phy_ctrl_t *pc);
     76 #endif
     77 
     78 #if defined(INCLUDE_FCMAP)
     79 /* BFCMAP TEST */ 
     80 #include <bcm/fcmap.h>
     81 extern int bfcmap_pcfg_set_get(int port);
     82 extern int bfcmap88060_xmod_debug_cmd(int unit, int port, int cmd);
     83 int bfcmap88060_show_fc_config(int unit, int port); 
     84 #endif
     85 extern int phy8806x_xmod_debug_cmd(int unit, int port);
     86 
     87 #include <bcm/port.h>
     88 #include <bcm/error.h>
     89 #include <bcm_int/control.h>
     90 
     91 #if defined(BCM_ESW_SUPPORT)
     92 #include <soc/xaui.h>
     93 #endif
     94 
     95 #define DUMP_PHY_COLS    4
     96 #define PHY_UPDATE(_flags, _control) ((_flags) & (1 << (_control)))
     97 #define IS_LONGREACH(_type) (((_type)>=BCM_PORT_PHY_CONTROL_LONGREACH_SPEED) && \
     98                             ((_type)<=BCM_PORT_PHY_CONTROL_LONGREACH_ENABLE))
     99 
    100 /* Note: See port.h, bcm_port_phy_control_t */
    101 char *phy_control[] = {
    102     "WAN                     ",
    103     "Preemphasis             ",
    104     "DriverCurrent           ",
    105     "PreDriverCurrent        ",
    106     "EqualizerBoost          ",
    107     "Interface               ",
    108     "InterfaceMAX            ",
    109     "MacsecSwitchFixed       ",
    110     "MacsecSwitchFixedSpeed  ",
    111     "MacsecSwitchFixedDuplex ",
    112     "MacsecSwitchFixedPause  ",
    113     "MacsecPauseRxForward    ",
    114     "MacsecPauseTxForward    ",
    115     "MacsecLineIPG           ",
    116     "MacsecSwitchIPG         ",
    117     "SPeed                   ",
    118     "PAirs                   ",
    119     "GAin                    ",
    120     "AutoNeg                 ",
    121     "LocalAbility            ",
    122     "RemoteAbility      (RO) ",
    123     "CurrentAbility     (RO) ",
    124     "MAster                  ",
    125     "Active             (RO) ",
    126     "ENable                  ",
    127     "PrePremphasis           ",
    128     "Encoding                ",
    129     "Scrambler               ",
    130     "PrbsPolynomial          ",
    131     "PrbsTxInvertData        ",
    132     "PrbsTxEnable            ",
    133     "PrbsRxEnable            ",
    134     "PrbsRxStatus            ",
    135     "SerdesDriverTune        ",
    136     "SerdesDriverEqualTuneStatus",
    137     "8b10b                   ",
    138     NULL
    139 };
    140 
    141 /* Note:  See eyescan.h soc_stat_eyscan_counter_e */
    142 char *eyescan_counter[] = {
    143     "RelativePhy", "PrbsPhy", "PrbsMac", "CrcMac", "BerMac", "Custom", NULL
    144 };
    145 
    146 
    147 cmd_result_t
    148 port_phy_control_update(int u, bcm_port_t p, bcm_port_phy_control_t type,
    149                         uint32 val, uint32 flags, int *print_header)
    150 {
    151     int rv;
    152     uint32 oval, flag_bit;
    153     char buffer[100];
    154 
    155     oval = 0;
    156     rv = bcm_port_phy_control_get(u, p, type, &oval);
    157     if (BCM_FAILURE(rv) && BCM_E_UNAVAIL != rv) {
    158         cli_out("%s\n", bcm_errmsg(rv));
    159         return CMD_FAIL;
    160     } else if (BCM_SUCCESS(rv)) {
    161         switch ( type ) {  /* for "phy clock" command */
    162             case BCM_PORT_PHY_CONTROL_CLOCK_ENABLE:
    163                 flag_bit = 0;
    164                 break;
    165             case BCM_PORT_PHY_CONTROL_CLOCK_SECONDARY_ENABLE:
    166                 flag_bit = 1;
    167                 break;
    168             case BCM_PORT_PHY_CONTROL_CLOCK_MODE_AUTO:
    169                 flag_bit = 3;
    170                 break;
    171             case BCM_PORT_PHY_CONTROL_CLOCK_AUTO_SECONDARY:
    172                 flag_bit = 4;
    173                 break;
    174             case BCM_PORT_PHY_CONTROL_FIRMWARE_DFE_ENABLE:
    175                 flag_bit = 8;
    176                 break;
    177             case BCM_PORT_PHY_CONTROL_FIRMWARE_LP_DFE_ENABLE:
    178                 flag_bit = 9;
    179                 break;
    180             case BCM_PORT_PHY_CONTROL_FIRMWARE_BR_DFE_ENABLE:
    181                 flag_bit = 10;
    182                 break;
    183             case BCM_PORT_PHY_CONTROL_CL72:
    184                 flag_bit = 11;
    185                 break;
    186             default:
    187                 flag_bit = type;
    188         }
    189         if ((val != oval) && PHY_UPDATE(flags, flag_bit)) {
    190             if (BCM_FAILURE(bcm_port_phy_control_set(u, p, type, val))) {
    191                 cli_out("%s\n", bcm_errmsg(rv));
    192                 return CMD_FAIL;
    193             }
    194             oval = val;
    195         }
    196         if (*print_header) {
    197             cli_out("Current PHY control settings of %s ->\n",
    198                     BCM_PORT_NAME(u, p));
    199             *print_header = FALSE;
    200         }
    201         if (IS_LONGREACH(type)) {
    202             switch (type) {
    203                 case BCM_PORT_PHY_CONTROL_LONGREACH_SPEED:
    204                 case BCM_PORT_PHY_CONTROL_LONGREACH_PAIRS:
    205                 case BCM_PORT_PHY_CONTROL_LONGREACH_GAIN:
    206                     sal_sprintf(buffer, "%d", oval);
    207                     break;
    208                 case BCM_PORT_PHY_CONTROL_LONGREACH_LOCAL_ABILITY:
    209                 case BCM_PORT_PHY_CONTROL_LONGREACH_REMOTE_ABILITY:
    210                 case BCM_PORT_PHY_CONTROL_LONGREACH_CURRENT_ABILITY:
    211                     format_phy_control_longreach_ability(buffer, sizeof(buffer),
    212                                                          (soc_phy_control_longreach_ability_t)
    213                                                          oval);
    214                     break;
    215                 case BCM_PORT_PHY_CONTROL_LONGREACH_AUTONEG:
    216                 case BCM_PORT_PHY_CONTROL_LONGREACH_MASTER:
    217                 case BCM_PORT_PHY_CONTROL_LONGREACH_ACTIVE:
    218                 case BCM_PORT_PHY_CONTROL_LONGREACH_ENABLE:
    219                     sal_sprintf(buffer, "%s", (oval == 1) ? "True" : "False");
    220                     break;
    221 
    222                 /* coverity[dead_error_begin] */
    223                 default:
    224                     buffer[0] = 0;
    225                     break;
    226 
    227             }
    228             cli_out("%s = %s\n", phy_control[type], buffer);
    229         } else if (type == BCM_PORT_PHY_CONTROL_LOOPBACK_EXTERNAL) {
    230             cli_out("        ENable = %s\n", (oval == 1) ? "True" : "False");
    231         } else if (type == BCM_PORT_PHY_CONTROL_CLOCK_ENABLE) {
    232             cli_out("Extraction to clock out (PRImary)          = %s\n",
    233                     (oval == 1) ? "Enabled" : "Disabled");
    234         } else if (type == BCM_PORT_PHY_CONTROL_CLOCK_SECONDARY_ENABLE) {
    235             cli_out("Extraction to clock out (SECondary)        = %s\n",
    236                     (oval == 1) ? "Enabled" : "Disabled");
    237         } else if (type == BCM_PORT_PHY_CONTROL_CLOCK_MODE_AUTO) {
    238             cli_out("Recovered clock auto Disable (AutoDisable) = %s\n",
    239                     (oval == 1) ? "Yes" : "No");
    240         } else if (type == BCM_PORT_PHY_CONTROL_CLOCK_AUTO_SECONDARY) {
    241             cli_out("Auto switch to Secondary   (AutoSECondary) = %s\n",
    242                     (oval == 1) ? "Yes" : "No");
    243         } else if (type == BCM_PORT_PHY_CONTROL_CLOCK_SOURCE) {
    244             cli_out("Recovery clock is being derived from       = %s\n",
    245                     (oval == bcmPortPhyClockSourcePrimary) ? "PRImary" : "SECondary");
    246         } else if (type == BCM_PORT_PHY_CONTROL_CLOCK_FREQUENCY) {
    247             cli_out("Extraction / Input (FR)equency             = %d KHz\n", oval);
    248         } else if (type == BCM_PORT_PHY_CONTROL_PORT_PRIMARY) {
    249             cli_out("(BA)se port of chip                        = %d\n", oval);
    250         } else if (type == BCM_PORT_PHY_CONTROL_PORT_OFFSET) {
    251             cli_out("Port (OF)fset within the chip              = %d\n", oval);
    252         } else if (type == BCM_PORT_PHY_CONTROL_FIRMWARE_DFE_ENABLE) {
    253             cli_out("DFE ENable               = %s\n", (oval == 1) ? "True" : "False");
    254         } else if (type == BCM_PORT_PHY_CONTROL_FIRMWARE_LP_DFE_ENABLE) {
    255             cli_out("LP DFE ENable            = %s\n", (oval == 1) ? "True" : "False");
    256         } else if (type == BCM_PORT_PHY_CONTROL_FIRMWARE_BR_DFE_ENABLE) {
    257             cli_out("BR DFE ENable            = %s\n", (oval == 1) ? "True" : "False");
    258         } else if (type == BCM_PORT_PHY_CONTROL_CL72) {
    259             cli_out("LinkTraining Enable      = %s\n", (oval == 1) ? "True" : "False");
    260         } else {
    261             cli_out("%s = 0x%0x\n", phy_control[type], oval);
    262         }
    263     }
    264     return CMD_OK;
    265 }
    266 
    267 int
    268 port_diag_ctrl(int unit, soc_port_t port,
    269                uint32 inst, int op_type, int op_cmd, void *arg)
    270 {
    271     int rv;
    272 #if defined(BCM_ESW_SUPPORT)
    273     if(SOC_IS_ESW(unit)) {
    274         PORT_LOCK(unit);
    275     }
    276 #endif
    277     {
    278 #ifdef PORTMOD_SUPPORT
    279         int is_legacy_phy = 0;
    280         int dev, is_internal = 0;
    281         if (soc_feature(unit, soc_feature_portmod)) {
    282             rv = portmod_port_is_legacy_ext_phy_present(unit, port, &is_legacy_phy);
    283             if (rv < 0) {
    284 #if defined(BCM_ESW_SUPPORT)
    285                 if(SOC_IS_ESW(unit)) {
    286                     PORT_UNLOCK(unit);
    287                 }
    288 #endif
    289                 return rv;
    290             }
    291             dev  = PHY_DIAG_INST_DEV(inst);
    292               if (dev == PHY_DIAG_DEV_DFLT) {
    293               is_internal = is_legacy_phy ? 0 : 1;
    294               } else if (dev == PHY_DIAG_DEV_INT) {
    295                   is_internal = 1;
    296               } else {
    297                   is_internal = 0;
    298               }
    299 
    300             if (is_internal) {
    301             rv = portmod_port_diag_ctrl(unit, port, inst, op_type, op_cmd, arg);
    302             } else {
    303                 if (!is_legacy_phy) {
    304                     rv = portmod_port_diag_ctrl(unit, port, inst, op_type, op_cmd, arg);
    305                 } else {
    306                     rv = soc_phyctrl_diag_ctrl(unit, port, inst, op_type, op_cmd, arg);
    307                 }
    308             }
    309         } else 
    310 #endif
    311         {
    312             rv = soc_phyctrl_diag_ctrl(unit, port, inst, op_type, op_cmd, arg);
    313         }
    314     }
    315 #if defined(BCM_ESW_SUPPORT)
    316     if(SOC_IS_ESW(unit)) {
    317         PORT_UNLOCK(unit);
    318     }
    319 #endif
    320     return rv;
    321 }
    322 
    323 /* definition for phy low power control command */
    324 typedef struct {
    325     bcm_pbmp_t pbm;
    326     int registered;
    327 } phy_power_ctrl_t;
    328 
    329 static phy_power_ctrl_t phy_pctrl_desc[SOC_MAX_NUM_DEVICES];
    330 
    331 STATIC void
    332 _phy_power_linkscan_cb(int unit, soc_port_t port, bcm_port_info_t *info)
    333 {
    334     int found = FALSE;
    335     soc_port_t p, dport;
    336     phy_power_ctrl_t *pDesc;
    337     bcm_port_cable_diag_t cds;
    338     int rv;
    339 
    340     pDesc = &phy_pctrl_desc[unit];
    341 
    342     /* coverity[overrun-local] */
    343     DPORT_BCM_PBMP_ITER(unit, pDesc->pbm, dport, p) {
    344         if (p == port) {
    345             found = TRUE;
    346             break;
    347         }
    348     }
    349 
    350     if (found == TRUE) {
    351         if (info->linkstatus == BCM_PORT_LINK_STATUS_UP) {
    352             /* link down->up transition */
    353 
    354             /* Check if giga link */
    355             if (info->speed != 1000) {
    356                 return;
    357             }
    358 
    359             /* Run cable diag if giga link */
    360             sal_memset(&cds, 0, sizeof(bcm_port_cable_diag_t));
    361             rv = bcm_port_cable_diag(unit, p, &cds);
    362             if (SOC_FAILURE(rv)) {
    363                 return;
    364             }
    365 
    366             if (cds.pair_len[0] >= 0 && cds.pair_len[0] < 10) {
    367                 /* Enable low power mode */
    368                 (void)bcm_port_phy_control_set(unit, p,
    369                                                BCM_PORT_PHY_CONTROL_POWER,
    370                                                BCM_PORT_PHY_CONTROL_POWER_LOW);
    371             }
    372         } else {
    373             /* link up->down transition */
    374             /* disable low-power mode */
    375             (void)bcm_port_phy_control_set(unit, p,
    376                                            BCM_PORT_PHY_CONTROL_POWER,
    377                                            BCM_PORT_PHY_CONTROL_POWER_FULL);
    378 
    379         }
    380     }
    381 }
    382 
    383 STATIC int
    384 _phy_auto_low_start(int unit, bcm_pbmp_t pbm, int enable)
    385 {
    386     soc_port_t p, dport;
    387     phy_power_ctrl_t *pDesc;
    388 
    389     pDesc = &phy_pctrl_desc[unit];
    390 
    391     if (enable) {
    392         if (!pDesc->registered) {
    393             pDesc->pbm = pbm;
    394             (void)bcm_linkscan_register(unit, _phy_power_linkscan_cb);
    395             pDesc->registered = TRUE;
    396         }
    397     } else {
    398         if (pDesc->registered) {
    399             (void)bcm_linkscan_unregister(unit, _phy_power_linkscan_cb);
    400             pDesc->registered = FALSE;
    401             /* coverity[overrun-local] */
    402             DPORT_BCM_PBMP_ITER(unit, pbm, dport, p) {
    403                 (void)bcm_port_phy_control_set(unit, p,
    404                                                BCM_PORT_PHY_CONTROL_POWER,
    405                                                BCM_PORT_PHY_CONTROL_POWER_FULL);
    406             }
    407         }
    408     }
    409     return SOC_E_NONE;
    410 }
    411 
    412 STATIC cmd_result_t
    413 _phy_diag_phy_unit_get(int unit_value, int *phy_dev)
    414 {
    415     *phy_dev = PHY_DIAG_DEV_DFLT;
    416     if (unit_value == 0) {      /* internal PHY */
    417         *phy_dev = PHY_DIAG_DEV_INT;
    418     } else if ((unit_value > 0) && (unit_value < 4)) {
    419         *phy_dev = PHY_DIAG_DEV_EXT;
    420     } else if (unit_value != -1) {
    421         cli_out("unit is numeric value: 0,1,2, ...\n");
    422         return CMD_FAIL;
    423     }
    424     return CMD_OK;
    425 }
    426 
    427 STATIC cmd_result_t
    428 _phy_diag_phy_if_get(char *if_str, int *dev_if)
    429 {
    430     *dev_if = PHY_DIAG_INTF_DFLT;
    431     if (if_str) {
    432         if (sal_strcasecmp(if_str, "sys") == 0) {
    433             *dev_if = PHY_DIAG_INTF_SYS;
    434         } else if (sal_strcasecmp(if_str, "line") == 0) {
    435             *dev_if = PHY_DIAG_INTF_LINE;
    436         } else if (if_str[0] != 0) {
    437             cli_out("InterFace must be sys or line.\n");
    438             return CMD_FAIL;
    439         }
    440     } else {
    441         cli_out("Invalid Interface string\n");
    442         return CMD_FAIL;
    443     }
    444     return CMD_OK;
    445 }
    446 
    447 STATIC cmd_result_t
    448 _phy_diag_loopback(int unit, bcm_pbmp_t pbmp, args_t *args)
    449 {
    450     parse_table_t pt;
    451     bcm_port_t port, dport;
    452     int rv=0;
    453     bcm_error_t bcm_res = BCM_E_NONE;
    454     cmd_result_t cmd_res = CMD_OK;
    455     char *if_str = NULL, *mode_str = NULL;
    456     int phy_unit = 0, phy_unit_value = -1, phy_unit_if;
    457     int pmd_status = 0, remote_status = 0, internal_status = 0;
    458     int mode = 0;
    459     uint32 inst;
    460 
    461     parse_table_init(unit, &pt);
    462     parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0),
    463                     &phy_unit_value, NULL);
    464     parse_table_add(&pt, "InterFace", PQ_STRING, 0, &if_str, NULL);
    465     parse_table_add(&pt, "mode", PQ_STRING, 0, &mode_str, NULL);
    466 
    467     if (parse_arg_eq(args, &pt) < 0) {
    468         cli_out("Error: invalid option: %s\n", ARG_CUR(args));
    469         parse_arg_eq_done(&pt);
    470         return CMD_USAGE;
    471     }
    472 
    473     cmd_res = _phy_diag_phy_if_get(if_str, &phy_unit_if);
    474     if (cmd_res == CMD_OK) {
    475         cmd_res = _phy_diag_phy_unit_get(phy_unit_value, &phy_unit);
    476     }
    477 
    478     if (mode_str && sal_strlen(mode_str)) {
    479         if (sal_strcasecmp(mode_str, "remote") == 0) {
    480             mode = 1;           /* remote loopback */
    481         } else if (sal_strcasecmp(mode_str, "local") == 0) {
    482             mode = 2;           /* internal loopback */
    483         } else if (sal_strcasecmp(mode_str, "global") == 0) {
    484             mode = 3;           /* global loopback */
    485         } else if (sal_strcasecmp(mode_str, "none") == 0) {
    486             mode = 0;           /* no loopback */
    487         } else {
    488             cli_out("valid modes: remote,local,global and none\n");
    489             cmd_res = CMD_FAIL;
    490         }
    491     } else {
    492             mode = -1;
    493     }
    494     /* Now free allocated strings */
    495     parse_arg_eq_done(&pt);
    496 
    497     if (cmd_res != CMD_OK) {
    498         return cmd_res;
    499     }
    500 
    501     inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, PHY_DIAG_LN_DFLT);
    502 
    503     /* coverity[overrun-local] */
    504     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
    505 
    506         if (mode > 0) {
    507             bcm_res = bcm_port_loopback_set(unit, port, 2); /* PHY */
    508 
    509             if (bcm_res != BCM_E_NONE) break;
    510 
    511             bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_LINE, PHY_DIAG_LN_DFLT) ,
    512                                    PHY_DIAG_CTRL_SET,
    513                                    SOC_PHY_CONTROL_LOOPBACK_INTERNAL,
    514                                    (void *)FALSE);
    515             if (bcm_res != BCM_E_NONE) break;
    516         }
    517 
    518         switch (mode) {
    519         case 3:
    520             bcm_res = port_diag_ctrl(unit, port, inst,
    521                                    PHY_DIAG_CTRL_SET,
    522                                    SOC_PHY_CONTROL_LOOPBACK_INTERNAL,
    523                                    (void *)TRUE);
    524             break;
    525         case 2:
    526             bcm_res = port_diag_ctrl(unit, port, inst,
    527                                    PHY_DIAG_CTRL_SET,
    528                                    SOC_PHY_CONTROL_LOOPBACK_PMD,
    529                                    (void *)TRUE);
    530             break;
    531         case 1:
    532             bcm_res = port_diag_ctrl(unit, port, inst,
    533                                    PHY_DIAG_CTRL_SET,
    534                                    SOC_PHY_CONTROL_LOOPBACK_REMOTE,
    535                                    (void *)TRUE);
    536             break;
    537 
    538         case 0:
    539             bcm_res = bcm_port_loopback_set(unit, port, 0);
    540 
    541             if (bcm_res != BCM_E_NONE) break;
    542 
    543             bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_LINE, PHY_DIAG_LN_DFLT),
    544                                    PHY_DIAG_CTRL_SET,
    545                                    SOC_PHY_CONTROL_LOOPBACK_PMD,
    546                                    (void *)FALSE);
    547             if (bcm_res!= BCM_E_NONE) break;
    548 
    549             bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_LINE, PHY_DIAG_LN_DFLT),
    550                                    PHY_DIAG_CTRL_SET,
    551                                    SOC_PHY_CONTROL_LOOPBACK_REMOTE,
    552                                    (void *)FALSE);
    553             if (bcm_res != BCM_E_NONE) break;
    554 
    555 
    556             bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_LINE, PHY_DIAG_LN_DFLT),
    557                                    PHY_DIAG_CTRL_SET,
    558                                    SOC_PHY_CONTROL_LOOPBACK_INTERNAL,
    559                                    (void *)FALSE);
    560             if (bcm_res != BCM_E_NONE) break;
    561 
    562             bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_SYS, PHY_DIAG_LN_DFLT),
    563                                    PHY_DIAG_CTRL_SET,
    564                                    SOC_PHY_CONTROL_LOOPBACK_PMD,
    565                                    (void *)FALSE);
    566             if (bcm_res != BCM_E_NONE) break;
    567 
    568             bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_SYS, PHY_DIAG_LN_DFLT),
    569                                    PHY_DIAG_CTRL_SET,
    570                                    SOC_PHY_CONTROL_LOOPBACK_REMOTE,
    571                                    (void *)FALSE);
    572             if (bcm_res != BCM_E_NONE) break;
    573 
    574             bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_SYS, PHY_DIAG_LN_DFLT),
    575                                    PHY_DIAG_CTRL_SET,
    576                                    SOC_PHY_CONTROL_LOOPBACK_INTERNAL,
    577                                    (void *)FALSE);
    578             break;
    579 
    580 
    581         case -1:
    582         default:
    583 
    584             bcm_res = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_GET,
    585                                        SOC_PHY_CONTROL_LOOPBACK_PMD,
    586                                        (void *)&pmd_status);
    587             if (bcm_res != BCM_E_NONE) break;
    588 
    589             bcm_res = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_GET,
    590                                        SOC_PHY_CONTROL_LOOPBACK_REMOTE,
    591                                        (void *)&remote_status);
    592             if (bcm_res != (int)BCM_E_NONE) break;
    593 
    594             bcm_res = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_GET,
    595                                        SOC_PHY_CONTROL_LOOPBACK_INTERNAL,
    596                                        (void *)&internal_status);
    597             if (bcm_res != (int)BCM_E_NONE) break;
    598             cli_out("Loopback Status: u=%d p=%d if=%s PMD=%d, PMD_REMOTE=%d, MAC=%d\n", unit, port,
    599                    (phy_unit_if & 0x1) ? "L" : "S",  pmd_status, remote_status, internal_status);
    600         }
    601 
    602     }
    603 
    604     if (bcm_res != BCM_E_NONE) {
    605         cli_out("Setting loopback failed: %s\n", bcm_errmsg(rv));
    606         return CMD_FAIL;
    607     }
    608 
    609     return CMD_OK;
    610 }
    611 
    612 STATIC cmd_result_t
    613 _phy_diag_dsc(int unit, bcm_pbmp_t pbmp, args_t *args)
    614 {
    615     parse_table_t pt;
    616     bcm_port_t port, dport;
    617     bcm_error_t rv = BCM_E_NONE;
    618     cmd_result_t cmd_result;
    619 
    620     char *if_str;
    621     int phy_unit, phy_unit_value = 0, phy_unit_if;
    622     uint32 inst;
    623     char *cmd_str = NULL;
    624 
    625     parse_table_init(unit, &pt);
    626 
    627     /*
    628      * unit:  phy_unit_value: phy chain number
    629      * if  :  if_str="sys"|"line"
    630      * 
    631      * in cases like phy diag xe0 dsc u=1 the string is not specified
    632      * Need to handle this case too.
    633      */
    634 
    635     if (args->a_argc > 4) {
    636         if (args->a_argv[4] && args->a_argv[4][0] != 'u') {
    637             cmd_str = ARG_GET(args);
    638         }
    639     }
    640 
    641     parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0),
    642                     &phy_unit_value, NULL);
    643     parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL);
    644     if (parse_arg_eq(args, &pt) < 0) {
    645         cli_out("Error: invalid option: %s\n", ARG_CUR(args));
    646         parse_arg_eq_done(&pt);
    647         return CMD_USAGE;
    648     }
    649 
    650     cmd_result = _phy_diag_phy_if_get(if_str, &phy_unit_if);
    651     if (cmd_result == CMD_OK) {
    652         cmd_result = _phy_diag_phy_unit_get(phy_unit_value, &phy_unit);
    653     }
    654 
    655     /* Now free allocated strings */
    656     parse_arg_eq_done(&pt);
    657 
    658     if (cmd_result != CMD_OK) {
    659         return cmd_result;
    660     }
    661 
    662     inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, PHY_DIAG_LN_DFLT);
    663 
    664     /* coverity[overrun-local] */
    665     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
    666         rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD,
    667                                    PHY_DIAG_CTRL_DSC, (void *)cmd_str);
    668         if (rv != BCM_E_NONE) {
    669             return CMD_FAIL;
    670         }
    671     }
    672     return CMD_OK;
    673 }
    674 
    675 cmd_result_t
    676 _phy_diag_pcs(int unit, bcm_pbmp_t pbmp, args_t *args)
    677 {
    678     parse_table_t pt;
    679     bcm_port_t port, dport;
    680     char *if_str;
    681     int phy_unit, phy_unit_value = 0, phy_unit_if;
    682     uint32 inst;
    683     char *cmd_str;
    684     bcm_error_t rv = BCM_E_NONE;
    685     cmd_result_t cmd_result;
    686 
    687     cmd_str = ARG_GET(args);
    688 
    689     parse_table_init(unit, &pt);
    690 
    691     /*
    692      * unit:  phy_unit_value: phy chain number
    693      * if  :  if_str="sys"|"line"
    694      */
    695     parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0),
    696                     &phy_unit_value, NULL);
    697     parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL);
    698     if (parse_arg_eq(args, &pt) < 0) {
    699         cli_out("Error: invalid option: %s\n", ARG_CUR(args));
    700         parse_arg_eq_done(&pt);
    701         return CMD_USAGE;
    702     }
    703 
    704     cmd_result = _phy_diag_phy_if_get(if_str, &phy_unit_if);
    705     if (cmd_result == CMD_OK) {
    706         cmd_result = _phy_diag_phy_unit_get(phy_unit_value, &phy_unit);
    707     }
    708 
    709 
    710     /* Now free allocated strings */
    711     parse_arg_eq_done(&pt);
    712 
    713     if (cmd_result != CMD_OK) {
    714         return cmd_result;
    715     }
    716 
    717     inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, PHY_DIAG_LN_DFLT);
    718 
    719     /* coverity[overrun-local] */
    720     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
    721         rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD,
    722                                    PHY_DIAG_CTRL_PCS, (void *)cmd_str);
    723         /* coverity[mixed_enums] */
    724         if (rv != BCM_E_NONE) {
    725             return CMD_FAIL;
    726         }
    727     }
    728     return CMD_OK;
    729 }
    730 
    731 #ifdef PHYMOD_LINKCAT_SUPPORT
    732 STATIC cmd_result_t
    733 _phy_diag_linkcat(int unit, bcm_pbmp_t pbmp, args_t *args)
    734 {
    735     parse_table_t pt;
    736     bcm_port_t port, dport;
    737     int lane; /* lane number specified on command line */ 
    738     char *mode = NULL;
    739     int mode_val = LINKCAT_LPBK_MODE; /* mode specified on command line. Default to lpbk */
    740     phymod_dispatch_type_t type = phymodDispatchTypeCount;
    741     phymod_access_t phy_acc;
    742     int num_lanes;
    743     int first_bit, mask;
    744     linkcat_config linkcat_config;
    745     linkcat_returns linkcat_status; 
    746     char *prefix = NULL;
    747     char prefix_str[50]; 
    748          
    749 
    750     if ( args->a_argc < 5) {
    751         return CMD_USAGE;
    752     }
    753     parse_table_init(unit, &pt);
    754     parse_table_add(&pt, "lane",  PQ_INT,
    755                     (void *)(0), &lane, NULL);
    756     parse_table_add(&pt, "mode", PQ_DFL | PQ_STRING,
    757                (void *)(0), &mode, NULL);
    758     parse_table_add(&pt, "prefix", PQ_DFL | PQ_STRING,
    759                (void *)(0), &prefix, NULL);
    760     if ( parse_arg_eq(args, &pt) < 0) {
    761         cli_out("Error: invalid option: %s\n", ARG_CUR(args));
    762         parse_arg_eq_done(&pt);
    763         return CMD_USAGE;
    764     }
    765 
    766     if ( mode != NULL ) {
    767         if ( !sal_strcasecmp(mode, "tx") ) {
    768             mode_val = LINKCAT_LPTX_MODE;
    769         } else if ( !sal_strcasecmp(mode, "rx") ) {
    770             mode_val = LINKCAT_RX_MODE;
    771         } else if ( !sal_strcasecmp(mode, "lpbk") ) {
    772             mode_val = LINKCAT_LPBK_MODE;
    773         } else {
    774             cli_out("Invalid mode parameter %s\n", mode); 
    775             return CMD_OK;
    776         }
    777     }
    778     sal_memset(prefix_str, 0, 50); 
    779     if ( prefix != NULL ) {
    780         sal_strncpy(prefix_str, prefix, 49); 
    781     }
    782 
    783     parse_arg_eq_done(&pt);
    784 
    785     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
    786         sal_memset(&phy_acc, 0, sizeof(phymod_access_t)); 
    787         num_lanes =  SOC_INFO(unit).port_num_lanes[port];
    788 
    789         if(soc_feature(unit, soc_feature_portmod)) {
    790 #ifdef PORTMOD_SUPPORT
    791             portmod_access_get_params_t params;
    792             phymod_core_access_t internal_core;
    793             phymod_phy_access_t access;
    794             int nof_phys, is_most_ext, max_phys = 1, nof_cores = 0;
    795 
    796             phymod_core_access_t_init(&internal_core);
    797             portmod_port_main_core_access_get(unit, port, 0, &internal_core, &nof_cores);
    798             if(nof_cores == 0) {
    799                 continue;
    800             }
    801             sal_memcpy(&phy_acc, &internal_core.access, sizeof(phymod_access_t));
    802             type = internal_core.type;
    803 
    804             params.phyn = 0; /* internal PHY */ 
    805             params.sys_side = PORTMOD_SIDE_LINE;
    806             params.lane = -1; /* request all lanes */
    807             params.apply_lane_mask = 0;
    808 
    809             portmod_port_phy_lane_access_get(unit, port, &params, max_phys, &access, &nof_phys, &is_most_ext);
    810             phy_acc.lane_mask = access.access.lane_mask;
    811 
    812         } else  
    813 #endif /* PORTMOD_SUPPORT */
    814         {
    815             phy_ctrl_t *pc;
    816             pc = INT_PHY_SW_STATE(unit, port);
    817             if (pc == NULL) {
    818                 continue;
    819             }
    820             sal_memcpy(&phy_acc, &pc->phymod_ctrl.phy[0]->pm_phy.access, sizeof(phymod_access_t));
    821             type = pc->phymod_ctrl.phy[0]->pm_phy.type; 
    822         }
    823 
    824         if ( phy_acc.bus == NULL || !phy_acc.addr || !phy_acc.lane_mask ) {
    825             cli_out("\nERROR: Unable to obtain PM core information for port %d\n. Command terminated", port); 
    826             return CMD_OK;
    827         }
    828 
    829         if ( lane >= num_lanes ) {
    830             cli_out("\nInvalid lane number %d. Port %d has only %d lanes (0x%x)\n", lane, port, num_lanes, phy_acc.lane_mask); 
    831             return CMD_OK;
    832         }
    833 
    834         mask = 0x1;
    835         for(first_bit = 0; first_bit < 32; first_bit++) {
    836            if ( (phy_acc.lane_mask & mask) ) { 
    837                 phy_acc.lane_mask = 1 << ( first_bit + lane ); 
    838                 break;
    839             }
    840             mask = mask << 1;
    841         }
    842         linkcat_status.insertion_loss = 0.0;
    843         linkcat_status.fit_factor = 0.0;
    844         linkcat_config.mode = mode_val; 
    845         linkcat_config.portaddress = phy_acc.addr; 
    846         linkcat_config.dir_name = NULL; 
    847         linkcat_config.file_prefix = prefix_str; 
    848 
    849         switch(type) {
    850             case phymodDispatchTypeBlackhawk:
    851             case phymodDispatchTypeTscbh: 
    852                 cli_out("Running linkCAT on addr=0x%x lane_mask=0x%x mode=%d\n", phy_acc.addr, phy_acc.lane_mask, mode_val); 
    853                 blackhawk_tsc_LinkCat(&phy_acc, &linkcat_config, &linkcat_status);
    854                 break;
    855             default:
    856                 cli_out("\nThis utility supports only PM8x50\n");  
    857                 return CMD_OK;
    858         }
    859     }
    860     return CMD_OK;
    861 }
    862 #endif /* PHYMOD_LINKCAT_SUPPORT */
    863 
    864 STATIC cmd_result_t
    865 _phy_diag_prbs(int unit, bcm_pbmp_t pbmp, args_t *args)
    866 {
    867     parse_table_t pt;
    868     bcm_port_t port, dport;
    869     int rv, cmd, enable;
    870     char *cmd_str, *if_str, *poly_str=NULL;
    871     int poly = 0, invert = 0, max_poly_index = 0;
    872     int phy_unit, phy_unit_value = -1, phy_unit_if;
    873     uint32 inst;
    874 
    875     enum { _PHY_PRBS_SET_CMD, _PHY_PRBS_GET_CMD, _PHY_PRBS_CLEAR_CMD };
    876     enum { _PHY_PRBS_SI_MODE, _PHY_PRBS_HC_MODE };
    877 
    878     if ((cmd_str = ARG_GET(args)) == NULL) {
    879         return CMD_USAGE;
    880     }
    881     if (sal_strcasecmp(cmd_str, "set") == 0) {
    882         cmd = _PHY_PRBS_SET_CMD;
    883         enable = 1;
    884     } else if (sal_strcasecmp(cmd_str, "get") == 0) {
    885         cmd = _PHY_PRBS_GET_CMD;
    886         enable = 0;
    887     } else if (sal_strcasecmp(cmd_str, "clear") == 0) {
    888         cmd = _PHY_PRBS_CLEAR_CMD;
    889         enable = 0;
    890     } else
    891         return CMD_USAGE;
    892 
    893     parse_table_init(unit, &pt);
    894     parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0),
    895                     &phy_unit_value, NULL);
    896     parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL);
    897     if (cmd == _PHY_PRBS_SET_CMD) {
    898         parse_table_add(&pt, "Polynomial", PQ_DFL | PQ_STRING,
    899                    (void *)(0), &poly_str, NULL);
    900         parse_table_add(&pt, "Invert", PQ_DFL | PQ_INT,
    901                         (void *)(0), &invert, NULL);
    902     }
    903     if (parse_arg_eq(args, &pt) < 0) {
    904         cli_out("Error: invalid option: %s\n", ARG_CUR(args));
    905         parse_arg_eq_done(&pt);
    906         return CMD_USAGE;
    907     }
    908 
    909     if ( poly_str ) {
    910         if ( !sal_strcasecmp(poly_str, "P7") || !sal_strcasecmp(poly_str, "0")) {
    911             poly = 0;
    912         } else if (!sal_strcasecmp(poly_str, "P15") || !sal_strcasecmp(poly_str, "1")  ) {
    913             poly = 1;
    914         } else if (!sal_strcasecmp(poly_str, "P23") || !sal_strcasecmp(poly_str, "2") ) {
    915             poly = 2;
    916         } else if (!sal_strcasecmp(poly_str, "P31") || !sal_strcasecmp(poly_str, "3") ) {
    917             poly = 3;
    918         } else if (!sal_strcasecmp(poly_str, "P9") || !sal_strcasecmp(poly_str, "4")) {
    919             poly = 4;
    920         } else if (!sal_strcasecmp(poly_str, "P11") || !sal_strcasecmp(poly_str, "5") ) {
    921             poly = 5;
    922         } else if (!sal_strcasecmp(poly_str, "P58") || !sal_strcasecmp(poly_str, "6")) {
    923             poly = 6;
    924 #ifdef BCM_TOMAHAWK3_SUPPORT
    925         } else if (SOC_IS_TOMAHAWK3(unit)) {
    926             if (!sal_strcasecmp(poly_str, "P49") || !sal_strcasecmp(poly_str, "7")) {
    927                 poly = 7;
    928             } else if (!sal_strcasecmp(poly_str, "P20") || !sal_strcasecmp(poly_str, "8")) {
    929                 poly = 8;
    930             } else if (!sal_strcasecmp(poly_str, "P13") || !sal_strcasecmp(poly_str, "9")) {
    931                 poly = 9;
    932             } else if (!sal_strcasecmp(poly_str, "P10") || !sal_strcasecmp(poly_str, "10")) {
    933                 poly = 10;
    934             } else {
    935                 cli_out("Prbs p must be P7(0), P15(1), P23(2), P31(3), P9(4), P11(5), P58(6), P49(7), P20(8), P13(9), or P10(10)\n");
    936                 return CMD_FAIL;
    937             }
    938 #endif /* BCM_TOMAHAWK3_SUPPORT */
    939         } else {
    940             cli_out("Prbs p must be P7(0), P15(1), P23(2), P31(3), P9(4), P11(5), or P58(6).\n");
    941             return CMD_FAIL;
    942         }
    943     }
    944 
    945     rv = (int)_phy_diag_phy_if_get(if_str, &phy_unit_if);
    946     if (rv == ((int)CMD_OK)) {
    947         rv = (int)_phy_diag_phy_unit_get(phy_unit_value, &phy_unit);
    948     }
    949 
    950     /* Now free allocated strings */
    951     parse_arg_eq_done(&pt);
    952 
    953     if (rv != CMD_OK) {
    954         return rv;
    955     }
    956 
    957     inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, PHY_DIAG_LN_DFLT);
    958 
    959     /* coverity[overrun-local] */
    960     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
    961         if (cmd == _PHY_PRBS_SET_CMD || cmd == _PHY_PRBS_CLEAR_CMD) {
    962             max_poly_index = 6;
    963 #ifdef BCM_TOMAHAWK3_SUPPORT
    964             if (SOC_IS_TOMAHAWK3(unit)) {
    965                 max_poly_index = 10;
    966             }
    967 #endif /* BCM_TOMAHAWK3_SUPPORT */
    968             if (poly >= 0 && poly <= max_poly_index) {
    969                 /* Set polynomial */
    970                 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_SET,
    971                                            SOC_PHY_CONTROL_PRBS_POLYNOMIAL,
    972                                            INT_TO_PTR(poly));
    973                 if (rv != ((int)BCM_E_NONE)) {
    974                     cli_out("Setting prbs polynomial failed: %s\n",
    975                             bcm_errmsg(rv));
    976                     return CMD_FAIL;
    977                 }
    978             } else {
    979                 cli_out("Polynomial must be 0..%d.\n", max_poly_index);
    980                 return CMD_FAIL;
    981             }
    982 
    983             /* Set invert */
    984             rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_SET,
    985                                        SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA,
    986                                        INT_TO_PTR(invert));
    987             if (rv != ((int)BCM_E_NONE)) {
    988                 cli_out("Setting prbs invertion failed: %s\n", bcm_errmsg(rv));
    989                 return CMD_FAIL;
    990             }
    991 
    992             rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_SET,
    993                                        SOC_PHY_CONTROL_PRBS_TX_ENABLE,
    994                                        INT_TO_PTR(enable));
    995             if (rv != ((int)BCM_E_NONE)) {
    996                 cli_out("Setting prbs tx enable failed: %s\n", bcm_errmsg(rv));
    997                 return CMD_FAIL;
    998             }
    999 
   1000             rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_SET,
   1001                                        SOC_PHY_CONTROL_PRBS_RX_ENABLE,
   1002                                        INT_TO_PTR(enable));
   1003             if (rv != ((int)BCM_E_NONE)) {
   1004                 cli_out("Setting prbs rx enable failed: %s\n", bcm_errmsg(rv));
   1005                 return CMD_FAIL;
   1006             }
   1007         } else {                /* _PHY_PRBS_GET_CMD */
   1008             int status;
   1009 
   1010             rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_GET,
   1011                                        SOC_PHY_CONTROL_PRBS_RX_STATUS,
   1012                                        (void *)&status);
   1013             if (rv != ((int)BCM_E_NONE)) {
   1014                 cli_out("Getting prbs rx status failed: %s\n", bcm_errmsg(rv));
   1015                 return CMD_FAIL;
   1016             }
   1017 
   1018             switch (status) {
   1019                 case 0:
   1020                     cli_out("%s (%2d):  PRBS OK!\n", BCM_PORT_NAME(unit, port),
   1021                             port);
   1022                     break;
   1023                 case -1:
   1024                     cli_out("%s (%2d):  PRBS Failed!\n",
   1025                             BCM_PORT_NAME(unit, port), port);
   1026                     break;
   1027                 default:
   1028                     cli_out("%s (%2d):  PRBS has %d errors!\n",
   1029                             BCM_PORT_NAME(unit, port), port, status);
   1030                     break;
   1031             }
   1032         }
   1033     }
   1034     return CMD_OK;
   1035 }
   1036 
   1037 STATIC cmd_result_t
   1038 _phy_diag_mfg(int unit, bcm_pbmp_t pbmp, args_t *args)
   1039 {
   1040 #ifndef  NO_FILEIO
   1041     parse_table_t pt;
   1042     bcm_port_t port, dport;
   1043     int rv, i, data_len = 0;
   1044     char *file_name = NULL, *buffer = NULL, *buf_ptr = NULL, *dptr;
   1045     int test, test_cmd = 0, num_ports, data;
   1046     FILE *ofp = NULL;
   1047 
   1048     parse_table_init(unit, &pt);
   1049     parse_table_add(&pt, "Test", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 0, &test, 0);
   1050     parse_table_add(&pt, "Data", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 0, &data, 0);
   1051     parse_table_add(&pt, "File", PQ_STRING, 0, &file_name, NULL);
   1052 
   1053     if (parse_arg_eq(args, &pt) < 0) {
   1054         cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   1055         parse_arg_eq_done(&pt);
   1056         return CMD_USAGE;
   1057     }
   1058 
   1059     switch (test) {
   1060         case 1:
   1061             test_cmd = PHY_DIAG_CTRL_MFG_HYB_CANC;
   1062             data_len = 770 * 4;
   1063             break;
   1064         case 2:
   1065             test_cmd = PHY_DIAG_CTRL_MFG_DENC;
   1066             data_len = 44 * 4;
   1067             break;
   1068         case 3:
   1069             test_cmd = PHY_DIAG_CTRL_MFG_TX_ON;
   1070             break;
   1071         case 0:
   1072             test_cmd = PHY_DIAG_CTRL_MFG_EXIT;
   1073             break;
   1074         default:
   1075             cli_out("Test should be : 1 (HYB_CANC), 2 (DENC), "
   1076                     "3 (TX_ON) or 0 (EXIT)\n");
   1077             parse_arg_eq_done(&pt);
   1078             return CMD_FAIL;
   1079             break;
   1080     }
   1081 
   1082     if (data_len) {
   1083         if ((ofp = sal_fopen(file_name, "w")) == NULL) {
   1084             cli_out("ERROR: Can't open the file : %s (for write)\n", file_name);
   1085             parse_arg_eq_done(&pt);
   1086             return CMD_FAIL;
   1087         }
   1088         switch (test) {
   1089             case 1:
   1090                 sal_fprintf(ofp, "PHY_DIAG_CTRL_MFG_HYB_CANC\n");
   1091                 break;
   1092             case 2:
   1093                 sal_fprintf(ofp, "PHY_DIAG_CTRL_MFG_DENC\n");
   1094                 break;
   1095         }
   1096     }
   1097 
   1098     /* Now free allocated strings */
   1099     parse_arg_eq_done(&pt);
   1100 
   1101     num_ports = 0;
   1102     /* coverity[overrun-local] */
   1103     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   1104         rv = port_diag_ctrl(unit, port, 0,
   1105                                    PHY_DIAG_CTRL_SET, test_cmd,
   1106                                    INT_TO_PTR(data));
   1107         if (rv != SOC_E_NONE) {
   1108             cli_out("Error: PHY_DIAG_CTRL_SET u=%d p=%d test_cmd=%d\n", unit,
   1109                     port, test_cmd);
   1110         }
   1111         num_ports++;
   1112     }
   1113 
   1114     /* every port has an extra 32 bit scratch pad */
   1115     buffer = sal_alloc(num_ports * (data_len + 32), "mfg_test_results");
   1116     if (buffer == NULL) {
   1117         cli_out("Insufficient memory.\n");
   1118         if (ofp) {
   1119             sal_fclose(ofp);
   1120         }
   1121         return CMD_FAIL;
   1122     }
   1123     buf_ptr = buffer;
   1124 
   1125     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   1126         buf_ptr[0] = 0;
   1127         rv = port_diag_ctrl(unit, port, 0,
   1128                                    PHY_DIAG_CTRL_GET, test_cmd,
   1129                                    (void *)(buf_ptr + 32));
   1130         if (rv != SOC_E_NONE) {
   1131             cli_out("Error: PHY_DIAG_CTRL_GET u=%d p=%d test_cmd=%d\n", unit,
   1132                     port, test_cmd);
   1133         } else {
   1134             buf_ptr[0] = -1;    /* indicates that the test result is valid */
   1135         }
   1136         buf_ptr += (data_len + 32);
   1137     }
   1138 
   1139     if (data_len) {
   1140         buf_ptr = buffer;
   1141         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   1142             i = 0;
   1143             dptr = buf_ptr + 32;
   1144             if (buf_ptr[0]) {
   1145                 sal_fprintf(ofp, "\n\nOutput data for port %s\n",
   1146                             BCM_PORT_NAME(unit, port));
   1147                 while (i < data_len) {
   1148                     if ((i & 0x1f) == 0) {      /* i % 32 */
   1149                         sal_fprintf(ofp, "\n");
   1150                     }
   1151                     /* data in ARM memory is big endian (network byte order) */
   1152                     sal_fprintf(ofp, "0x%08x", soc_ntohl_load(dptr));
   1153                     dptr += 4;
   1154                     i += 4;
   1155                     if (i >= data_len) {
   1156                         sal_fprintf(ofp, "\n");
   1157                         break;
   1158                     } else {
   1159                         sal_fprintf(ofp, ", ");
   1160                     }
   1161                 }
   1162             } else {
   1163                 sal_fprintf(ofp, "\n\nTest failed for port %s\n",
   1164                             BCM_PORT_NAME(unit, port));
   1165             }
   1166             buf_ptr += (data_len + 32);
   1167         }
   1168     }
   1169 
   1170     if (ofp) {
   1171         sal_fclose(ofp);
   1172     }
   1173     sal_free(buffer);
   1174 
   1175     return CMD_OK;
   1176 #else
   1177     cli_out("This command is not supported without file I/O\n");
   1178     return CMD_FAIL;
   1179 #endif
   1180 }
   1181 
   1182 STATIC cmd_result_t
   1183 _phy_diag_state(int unit, bcm_pbmp_t pbmp, args_t *args)
   1184 {
   1185 #ifndef  NO_FILEIO
   1186     parse_table_t pt;
   1187     bcm_port_t port, dport;
   1188     int rv, i, data_len = 0;
   1189     char *file_name = NULL, *buffer = NULL, *buf_ptr = NULL, *dptr;
   1190     XGPHY_DIAG_DATA_t *diag_dptr;
   1191     int test, test_cmd = 0, num_ports, data;
   1192     FILE *ofp = NULL;
   1193 
   1194     parse_table_init(unit, &pt);
   1195     parse_table_add(&pt, "Test", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 0, &test, 0);
   1196     parse_table_add(&pt, "Data", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 0, &data, 0);
   1197     parse_table_add(&pt, "File", PQ_STRING, 0, &file_name, NULL);
   1198 
   1199     if (parse_arg_eq(args, &pt) < 0) {
   1200         cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   1201         parse_arg_eq_done(&pt);
   1202         return CMD_USAGE;
   1203     }
   1204 
   1205     switch (test) {
   1206         case 1:
   1207             test_cmd = PHY_DIAG_CTRL_STATE_TRACE1;
   1208             data_len = 2048 * 4;
   1209             break;
   1210         case 2:
   1211             test_cmd = PHY_DIAG_CTRL_STATE_TRACE2;
   1212             data_len = 1024 * 4;
   1213             break;
   1214         case 3:
   1215             test_cmd = PHY_DIAG_CTRL_STATE_WHEREAMI;
   1216             data_len = sizeof(XGPHY_DIAG_DATA_t);
   1217             break;
   1218         case 4:
   1219             test_cmd = PHY_DIAG_CTRL_STATE_TEMP;
   1220             data_len = sizeof(XGPHY_DIAG_DATA_t);
   1221             break;
   1222         case 5:
   1223             test_cmd = PHY_DIAG_CTRL_STATE_GENERIC;
   1224             break;
   1225         default:
   1226             cli_out("Test should be : 1 (STATE_TRACE1), 2 (STATE_TRACE2), "
   1227                     "3 (WHERE_AM_I), 4 (TEMP)\n");
   1228             parse_arg_eq_done(&pt);
   1229             return CMD_FAIL;
   1230             break;
   1231     }
   1232 
   1233     if (data_len) {
   1234         if ((ofp = sal_fopen(file_name, "a+")) == NULL) {
   1235             cli_out("ERROR: Can't open the file : %s\n", file_name);
   1236             parse_arg_eq_done(&pt);
   1237             return CMD_FAIL;
   1238         }
   1239         sal_fprintf(ofp,
   1240                    "\n-------------------------------------------------------"
   1241                    "------------------------------------------------------\n");
   1242         switch (test) {
   1243             case 1:
   1244                 sal_fprintf(ofp, "PHY_DIAG_CTRL_STATE_TRACE1\n");
   1245                 break;
   1246             case 2:
   1247                 sal_fprintf(ofp, "PHY_DIAG_CTRL_STATE_TRACE2\n");
   1248                 break;
   1249             case 3:
   1250                 sal_fprintf(ofp, "PHY_DIAG_CTRL_STATE_WHERE_AM_I\n");
   1251                 break;
   1252             case 4:
   1253                 sal_fprintf(ofp, "PHY_DIAG_CTRL_STATE_TEMP\n");
   1254                 break;
   1255         }
   1256     }
   1257 
   1258     /* Now free allocated strings */
   1259     parse_arg_eq_done(&pt);
   1260 
   1261     num_ports = 0;
   1262     /* coverity[overrun-local] */
   1263     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   1264         rv = port_diag_ctrl(unit, port, 0,
   1265                             PHY_DIAG_CTRL_SET, test_cmd,
   1266                             INT_TO_PTR(data));
   1267         if (rv != SOC_E_NONE) {
   1268             cli_out("Error: PHY_DIAG_CTRL_SET u=%d p=%d test_cmd=%d\n", unit,
   1269                     port, test_cmd);
   1270         }
   1271         num_ports++;
   1272     }
   1273 
   1274     /* every port has an extra 32 bit scratch pad */
   1275     buffer = sal_alloc(num_ports * (data_len + 32), "state_test_results");
   1276     if (buffer == NULL) {
   1277         cli_out("Insufficient memory.\n");
   1278         if (ofp) {
   1279             sal_fclose(ofp);
   1280         }
   1281         return CMD_FAIL;
   1282     }
   1283     buf_ptr = buffer;
   1284 
   1285     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   1286         buf_ptr[0] = 0;
   1287         rv = port_diag_ctrl(unit, port, 0,
   1288                             PHY_DIAG_CTRL_GET, test_cmd,
   1289                             (void *)(buf_ptr + 32));
   1290         if (rv != SOC_E_NONE) {
   1291             cli_out("Error: PHY_DIAG_CTRL_GET u=%d p=%d test_cmd=%d\n", unit,
   1292                     port, test_cmd);
   1293         } else {
   1294             buf_ptr[0] = -1;    /* indicates that the test result is valid */
   1295         }
   1296         buf_ptr += (data_len + 32);
   1297     }
   1298 
   1299     if (data_len) {
   1300         buf_ptr = buffer;
   1301         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   1302             i = 0;
   1303             dptr = buf_ptr + 32;
   1304             diag_dptr = (XGPHY_DIAG_DATA_t *) dptr;
   1305 
   1306             if (buf_ptr[0]) {
   1307                 sal_fprintf(ofp, "\n\nOutput data for port %s\n",
   1308                             BCM_PORT_NAME(unit, port));
   1309                 if (test_cmd == PHY_DIAG_CTRL_STATE_WHEREAMI) {
   1310                     int32 valA, valB, valC, valD, statA, statB, statC, statD;
   1311 
   1312                     if (diag_dptr->flags & PHY_DIAG_FULL_SNR_SUPPORT) {
   1313                         valA =
   1314                             soc_letohl_load(&diag_dptr->snr_block[16]) - 32768;
   1315                         valB =
   1316                             soc_letohl_load(&diag_dptr->snr_block[20]) - 32768;
   1317                         valC =
   1318                             soc_letohl_load(&diag_dptr->snr_block[24]) - 32768;
   1319                         valD =
   1320                             soc_letohl_load(&diag_dptr->snr_block[28]) - 32768;
   1321 
   1322                         statA = soc_letohl_load(&diag_dptr->snr_block[0]);
   1323                         statB = soc_letohl_load(&diag_dptr->snr_block[4]);
   1324                         statC = soc_letohl_load(&diag_dptr->snr_block[8]);
   1325                         statD = soc_letohl_load(&diag_dptr->snr_block[12]);
   1326 
   1327                         sal_fprintf(ofp,
   1328                                     "\nsnrA = %d.%d (%s) snrB = %d.%d (%s) "
   1329                                     "snrC = %d.%d (%s) snrD = %d.%d (%s) "
   1330                                     "serr = %d cerr = %d block_lock = %d "
   1331                                     "block_point_id = %d\n",
   1332                                     valA / 10, valA % 10,
   1333                                     statA ? "OK" : "Not OK", valB / 10,
   1334                                     valB % 10, statB ? "OK" : "Not OK",
   1335                                     valC / 10, valC % 10,
   1336                                     statC ? "OK" : "Not OK", valD / 10,
   1337                                     valD % 10, statD ? "OK" : "Not OK",
   1338                                     diag_dptr->serr, diag_dptr->cerr,
   1339                                     diag_dptr->block_lock,
   1340                                     diag_dptr->block_point_id);
   1341 
   1342                     } else {
   1343                         valA = soc_letohl_load(&diag_dptr->snr_block[0]);
   1344                         valB = soc_letohl_load(&diag_dptr->snr_block[4]);
   1345                         valC = soc_letohl_load(&diag_dptr->snr_block[8]);
   1346                         valD = soc_letohl_load(&diag_dptr->snr_block[12]);
   1347 
   1348                         sal_fprintf(ofp,
   1349                                     "\nmseA = %d mseB = %d mseC = %d mseD = %d "
   1350                                     "serr = %d cerr = %d block_lock = 0x%x "
   1351                                     "block_point_id = 0x%x\n",
   1352                                     valA, valB, valC, valD, diag_dptr->serr,
   1353                                     diag_dptr->cerr, diag_dptr->block_lock,
   1354                                     diag_dptr->block_point_id);
   1355                     }
   1356                 } else if (test_cmd == PHY_DIAG_CTRL_STATE_TEMP) {
   1357                     sal_fprintf(ofp, "\nTemperature = %d C,  %d F\n",
   1358                                 diag_dptr->digital_temp,
   1359                                 (diag_dptr->digital_temp * 9) / 5 + 32);
   1360                 } else {
   1361                     while (i < data_len) {
   1362                         if ((i & 0x1f) == 0) {  /* i % 32 */
   1363                             sal_fprintf(ofp, "\n");
   1364                         }
   1365                         sal_fprintf(ofp, "0x%08x", soc_letohl_load(&dptr[0]));
   1366                         dptr += 4;
   1367                         i += 4;
   1368                         if (i >= data_len) {
   1369                             sal_fprintf(ofp, "\n");
   1370                             break;
   1371                         } else {
   1372                             sal_fprintf(ofp, ", ");
   1373                         }
   1374                     }
   1375                 }
   1376             } else {
   1377                 sal_fprintf(ofp, "\n\nTest failed for port %s\n",
   1378                             BCM_PORT_NAME(unit, port));
   1379             }
   1380             buf_ptr += (data_len + 32);
   1381         }
   1382     }
   1383 
   1384     if (ofp) {
   1385         sal_fclose(ofp);
   1386     }
   1387     sal_free(buffer);
   1388 
   1389     return CMD_OK;
   1390 #else
   1391     cli_out("This command is not supported without file I/O\n");
   1392     return CMD_FAIL;
   1393 #endif
   1394 }
   1395 
   1396 STATIC cmd_result_t
   1397 _phy_diag_fast_eyescan(int unit, bcm_pbmp_t pbmp, args_t *args)
   1398 {
   1399     parse_table_t pt;
   1400     bcm_port_t port, dport;
   1401     int rv=0,res=0;
   1402     char *if_str;
   1403     int phy_unit = 0, phy_unit_value = 0, phy_unit_if = 0;
   1404     int lane_num = 0;
   1405     uint32 inst;
   1406 
   1407     parse_table_init(unit, &pt);
   1408 
   1409     /*
   1410      * unit:  phy_unit_value: phy chain number
   1411      * if  :  if_str="sys"|"line"
   1412      */
   1413     parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0),
   1414                     &phy_unit_value, NULL);
   1415     parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL);
   1416     parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0), &lane_num, NULL);
   1417 
   1418     if (parse_arg_eq(args, &pt) < 0) {
   1419         cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   1420         parse_arg_eq_done(&pt);
   1421         return CMD_USAGE;
   1422     }
   1423 
   1424     rv = _phy_diag_phy_if_get(if_str, &phy_unit_if);
   1425     if (rv == CMD_OK) {
   1426         rv = _phy_diag_phy_unit_get(phy_unit_value, &phy_unit);
   1427     }
   1428 
   1429     /* Now free allocated strings */
   1430     parse_arg_eq_done(&pt);
   1431 
   1432     if (rv != CMD_OK) {
   1433         return rv;
   1434     }
   1435 
   1436     inst =
   1437         PHY_DIAG_INSTANCE(phy_unit, phy_unit_if,
   1438                           (lane_num == 0xff) ? PHY_DIAG_LN_DFLT : lane_num);
   1439 
   1440     /* coverity[overrun-local] */
   1441     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   1442         res = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD,
   1443                                    PHY_DIAG_CTRL_START_FAST_EYESCAN, (void *)0);
   1444         if (res != BCM_E_NONE) {
   1445             return CMD_FAIL;
   1446         }
   1447     }
   1448     return CMD_OK;
   1449 }
   1450 
   1451 STATIC cmd_result_t
   1452 _phy_diag_link_mon(int unit, bcm_pbmp_t pbmp, args_t *args)
   1453 {
   1454     parse_table_t pt;
   1455     bcm_port_t port, dport;
   1456     int rv;
   1457     char *cmd_str, *if_str;
   1458     int phy_unit = 0, phy_unit_value = 0, phy_unit_if = 0;
   1459     int lane_num = 0;
   1460     uint32 link_mon_mode = 0, cmd;
   1461     uint32 inst;
   1462 
   1463     enum { _PHY_LINKMON_SET_CMD, _PHY_LINKMON_GET_CMD};
   1464     parse_table_init(unit, &pt);
   1465 
   1466     if ((cmd_str = ARG_GET(args)) == NULL) {
   1467         return CMD_USAGE;
   1468     }
   1469     if (sal_strcasecmp(cmd_str, "set") == 0) {
   1470         cmd = _PHY_LINKMON_SET_CMD;
   1471     } else if (sal_strcasecmp(cmd_str, "get") == 0) {
   1472         cmd = _PHY_LINKMON_GET_CMD;
   1473     } else {
   1474         return CMD_USAGE;
   1475     }
   1476 
   1477     /*
   1478      * unit:  phy_unit_value: phy chain number
   1479      * if  :  if_str="sys"|"line"
   1480      */
   1481     parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0),
   1482                     &phy_unit_value, NULL);
   1483     parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL);
   1484     parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0), &lane_num, NULL);
   1485     if (cmd == _PHY_LINKMON_SET_CMD) {
   1486         parse_table_add(&pt, "mode", PQ_DFL | PQ_INT, (void *)(0), &link_mon_mode, NULL);
   1487     }
   1488 
   1489     if (parse_arg_eq(args, &pt) < 0) {
   1490         cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   1491         parse_arg_eq_done(&pt);
   1492         return CMD_USAGE;
   1493     }
   1494 
   1495     rv = (int)_phy_diag_phy_if_get(if_str, &phy_unit_if);
   1496     if (rv == ((int)CMD_OK)) {
   1497         rv = (int)_phy_diag_phy_unit_get(phy_unit_value, &phy_unit);
   1498     }
   1499 
   1500     /* Now free allocated strings */
   1501     parse_arg_eq_done(&pt);
   1502 
   1503     if (rv != ((int)CMD_OK)) {
   1504         return rv;
   1505     }
   1506 
   1507     inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, lane_num);
   1508 
   1509     /* coverity[overrun-local] */
   1510     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   1511 
   1512 #ifdef PORTMOD_SUPPORT
   1513         if (soc_feature(unit, soc_feature_portmod)) {
   1514             if (cmd == _PHY_LINKMON_SET_CMD) {
   1515                 rv = portmod_port_diag_ctrl( unit, port, inst, PHY_DIAG_CTRL_CMD,
   1516                                             PHY_DIAG_CTRL_LINKMON_MODE, INT_TO_PTR(link_mon_mode));
   1517             } else {
   1518                 rv = portmod_port_diag_ctrl( unit, port, inst, PHY_DIAG_CTRL_CMD,
   1519                                             PHY_DIAG_CTRL_LINKMON_STATUS,(void *)0);
   1520             }
   1521         } else
   1522 #endif
   1523         {
   1524         
   1525             if (cmd == _PHY_LINKMON_SET_CMD) {
   1526                 rv = soc_phyctrl_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD,
   1527                                            PHY_DIAG_CTRL_LINKMON_MODE, INT_TO_PTR(link_mon_mode));
   1528             } else {
   1529                 rv = soc_phyctrl_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD,
   1530                                            PHY_DIAG_CTRL_LINKMON_STATUS, (void *)0);
   1531             }
   1532         }
   1533     
   1534         if (rv != ((int)BCM_E_NONE)) {
   1535             return CMD_FAIL;
   1536         }
   1537     }
   1538     return CMD_OK;
   1539 }
   1540 
   1541 STATIC int
   1542 _phy_diag_eyescan_res_print(int unit,
   1543                             int speed,
   1544                             soc_port_t port,
   1545                             int sample_res,
   1546                             soc_port_phy_eye_bounds_t *bounds,
   1547                             soc_port_phy_eyescan_results_t *res)
   1548 {
   1549 
   1550     int vt_i, hz_i, legend_ndx = 0, legend_ndx_offset = 0;
   1551     int hz_min, hz_max, vt_min, vt_max;
   1552     const char legend[] = { ' ', '.', 'o', 'b', 'P', 'D', 'B', 'M', 'W', 'X' };
   1553     const char legend_low_ber[] =
   1554         { ' ', 'X', 'W', 'M', 'B', 'D', 'P', 'b', 'o', '.', 'Y', 'Z', 'A' };
   1555     const char error_char = '!';
   1556     const char invalid_char = '?';
   1557     int desc_idx = 0;
   1558     unsigned int error_cnt;
   1559     unsigned int time_tot;
   1560     cmd_result_t ret = CMD_OK;
   1561     phy_ctrl_t *pc;
   1562 
   1563 #if defined(BROADCOM_DEBUG)     /*required for compilation */
   1564     char *description[] = {
   1565         "   Description:",
   1566         "   =============",
   1567         "   '+'  Latch",
   1568         "   '?'  No data"
   1569     };
   1570 #endif                          /*BROADCOM_DEBUG */
   1571     int desc_size = 4;
   1572 
   1573 #if defined(BROADCOM_DEBUG)     /*required for compilation */
   1574     char *desc_ber[] = {
   1575         "   '%c' BER <10-9",
   1576         "   '%c' BER ~10-9",
   1577         "   '%c' BER ~10-8",
   1578         "   '%c' BER ~10-7",
   1579         "   '%c' BER ~10-6",
   1580         "   '%c' BER ~10-5",
   1581         "   '%c' BER ~10-4",
   1582         "   '%c' BER ~10-3",
   1583         "   '%c' BER ~10-2",
   1584         "   '%c' BER >10-2"
   1585     };
   1586     char *desc_low_ber[] = {
   1587         "   '%c' BER <10-12",
   1588         "   '%c' BER >10-2",
   1589         "   '%c' BER ~10-2",
   1590         "   '%c' BER ~10-3",
   1591         "   '%c' BER ~10-4",
   1592         "   '%c' BER ~10-5",
   1593         "   '%c' BER ~10-6",
   1594         "   '%c' BER ~10-7",
   1595         "   '%c' BER ~10-8",
   1596         "   '%c' BER ~10-9",
   1597         "   '%c' BER ~10-10",
   1598         "   '%c' BER ~10-11",
   1599         "   '%c' BER ~10-12"
   1600     };
   1601 #endif                          /*BROADCOM_DEBUG */
   1602     int desc_ber_size = 10;
   1603     int desc_low_ber_size = 13;
   1604 
   1605 
   1606     const unsigned int nof_legend_chars = sizeof(legend) / sizeof(char);
   1607     const unsigned int nof_legend_low_ber_chars =
   1608         sizeof(legend_low_ber) / sizeof(char);
   1609     char print_char;
   1610     unsigned int ber;
   1611     char buf[5];
   1612     unsigned int rev_ber = 0;
   1613     unsigned int bits_xferred = 0;
   1614     unsigned int gspeed = 0;    /* Speed in Gbps */
   1615     unsigned int speed_n = 0;   /* Normalized speed */
   1616     unsigned int time_n = 0;    /* Normalized time */
   1617 
   1618     pc = EXT_PHY_SW_STATE(unit, port);
   1619 
   1620     if (!BCM_UNIT_VALID(unit)) {
   1621         ret = CMD_FAIL;
   1622         goto exit;
   1623     }
   1624 
   1625     /*psrsmeters verification */
   1626     if (0 == bounds) {
   1627         ret = CMD_FAIL;
   1628         goto exit;
   1629     }
   1630 
   1631     hz_min = bounds->horizontal_min;
   1632     hz_max = bounds->horizontal_max;
   1633     vt_min = bounds->vertical_min;
   1634     vt_max = bounds->vertical_max;    
   1635 
   1636     if (hz_max < hz_min) {
   1637         ret = CMD_FAIL;
   1638         goto exit;
   1639     }
   1640     if (vt_max < vt_min) {
   1641         ret = CMD_FAIL;
   1642         goto exit;
   1643     }
   1644 
   1645     if (0 == res) {
   1646         ret = CMD_FAIL;
   1647         goto exit;
   1648     }
   1649 
   1650     /*Print results log */
   1651     for (vt_i = vt_min; vt_i <= vt_max; vt_i++) {
   1652         if (vt_i % sample_res != 0) {
   1653             continue;
   1654         }
   1655         for (hz_i = hz_min; hz_i <= hz_max; hz_i++) {
   1656             if (hz_i % sample_res != 0) {
   1657                 continue;
   1658             }
   1659 
   1660             cli_out("[H=%d, V=%d] %u errors in %d milisec \r\n", hz_i, vt_i,
   1661                     res->error_count[hz_i + SOC_PORT_PHY_EYESCAN_H_INDEX]
   1662                     [vt_i + SOC_PORT_PHY_EYESCAN_V_INDEX],
   1663                     res->run_time[hz_i + SOC_PORT_PHY_EYESCAN_H_INDEX]
   1664                     [vt_i + SOC_PORT_PHY_EYESCAN_V_INDEX]);
   1665         }
   1666     }
   1667 
   1668     if (res->ext_done) {
   1669         switch (res->ext_better) {
   1670             case -1:
   1671                 cli_out("BER(extrapolated) is *worse* than 1e-%d.%d\n",
   1672                         res->ext_results_int, res->ext_results_remainder);
   1673                 break;
   1674             case 1:
   1675                 cli_out("BER(extrapolated) is *better* than 1e-%d.%d\n",
   1676                         res->ext_results_int, res->ext_results_remainder);
   1677                 break;
   1678             default:
   1679                 cli_out("BER(extrapolated) = 1e-%d.%d\n", res->ext_results_int,
   1680                         res->ext_results_remainder);
   1681                 break;
   1682         }
   1683     }
   1684 
   1685     if (hz_max != hz_min) {
   1686         cli_out("\r\n[VERTICAL]-------------------------------"
   1687                 "------------------------\r\n");
   1688         for (vt_i = vt_max; vt_i >= vt_min; vt_i--) {
   1689             if (vt_i % sample_res != 0) {
   1690                 continue;
   1691             }
   1692 
   1693             /* Print Y axis and values */
   1694             if ((((vt_i - vt_min) / sample_res) % 5 == 0)) {
   1695                 cli_out("%3d-+", vt_i);
   1696             } else {
   1697                 cli_out("    |");
   1698             }
   1699 
   1700             for (hz_i = hz_min; hz_i <= hz_max; hz_i++) {
   1701 
   1702                 if (hz_i % sample_res != 0) {
   1703                     continue;
   1704                 }
   1705 
   1706                 print_char = error_char;
   1707                 error_cnt =
   1708                     res->error_count[hz_i + SOC_PORT_PHY_EYESCAN_H_INDEX]
   1709                                     [vt_i + SOC_PORT_PHY_EYESCAN_V_INDEX];
   1710                 time_tot =
   1711                     res->run_time[hz_i + SOC_PORT_PHY_EYESCAN_H_INDEX]
   1712                                  [vt_i + SOC_PORT_PHY_EYESCAN_V_INDEX];
   1713 
   1714                 if (time_tot == 0 && error_cnt == 0) {
   1715                     print_char = invalid_char;
   1716                 } else {
   1717                     /*
   1718                      * Eyescan calculation for Low BER 
   1719                      * -------------------------------
   1720                      *   Standard/Existing eyescan plot function was supporting
   1721                      * upto BER 10^-9 below logic is implemented for plotting
   1722                      * eyescan for BER 10^-10, 10^-11, 10^-12 for satisfying
   1723                      * low BER requirements. Currently this logic is implemented
   1724                      * for Gallardo40 to fix the JIRA PHY-1156.
   1725                      *      BER = #bit errors/#bit transferred
   1726                      * For testing low BER we need to run eyescan for long
   1727                      * sample time. For Ex: We may have to run eyescan for 10E5
   1728                      * milli sec with 10G traffic to see BER 10^-12
   1729                      * i.e., #bits transferred in 10^5 millisec = 10^12
   1730                      * if #bit errors = 1, BER = 1 / 10^12 = 10^-12
   1731                      * The below logic is implemented using uint32 so as to 
   1732                      * avoid the usage of uint64, Float, math library functions
   1733                      * such as log, abs, ceil, floor these have performance
   1734                      * issues and prone to introduce build issues in our SDK
   1735                      * environment. uint32 can store max 2^32
   1736                      * (cannot store 10^12), and actual BER requires
   1737                      * Float (#biterrors/#bits transferred, We calculate
   1738                      * Reverse BER, calculating index of legend_low_ber by
   1739                      * calculating no of digits present in reverse BER to print
   1740                      * the char for plotting eyescan
   1741                      *          rev_ber = bits_xferred / error_cnt;
   1742                      *          legend_ndx = #digits(rev_ber);
   1743                      *          print_char = legend_low_ber[legend_ndx];
   1744                      * Below is the map between print_char and BER
   1745                      * =============
   1746                      * '+'  Latch
   1747                      * '?'  No data
   1748                      * ' ' BER <10-12
   1749                      * 'X' BER >10-2
   1750                      * 'W' BER ~10-2
   1751                      * 'M' BER ~10-3
   1752                      * 'B' BER ~10-4
   1753                      * 'D' BER ~10-5
   1754                      * 'P' BER ~10-6
   1755                      * 'b' BER ~10-7
   1756                      * 'o' BER ~10-8
   1757                      * '.' BER ~10-9
   1758                      * 'Y' BER ~10-10
   1759                      * 'Z' BER ~10-11
   1760                      * 'A' BER ~10-12
   1761                      */
   1762                     if (pc && pc->phy_id0 == 0x600d && pc->phy_id1 == 0x8500) {
   1763                         if (time_tot == 0) {
   1764                             legend_ndx = 0;
   1765                         } else {
   1766                             time_n = 1;
   1767                             while (time_n <= 1000000) {
   1768                                 if (time_tot <= time_n) {
   1769                                     break;
   1770                                 }
   1771                                 time_n *= 10;
   1772                             }
   1773 
   1774                             gspeed = speed / 1000;
   1775                             speed_n = 1;
   1776                             while (speed_n <= 100) {
   1777                                 if (gspeed <= speed_n) {
   1778                                     break;
   1779                                 }
   1780                                 speed_n *= 10;
   1781                             }
   1782 
   1783                             switch (time_n * speed_n) {
   1784                                 case 1:
   1785                                 case 10:
   1786                                 case 100:
   1787                                 case 1000:
   1788                                     bits_xferred = gspeed * 1000000 * time_tot;
   1789                                     legend_ndx_offset = 0;
   1790                                     break;
   1791                                 case 10000:
   1792                                     bits_xferred = gspeed * 100000 * time_tot;
   1793                                     legend_ndx_offset = 1;
   1794                                     break;
   1795                                 case 100000:
   1796                                     bits_xferred = gspeed * 10000 * time_tot;
   1797                                     legend_ndx_offset = 2;
   1798                                     break;
   1799                                 case 1000000:
   1800                                     bits_xferred = gspeed * 1000 * time_tot;
   1801                                     legend_ndx_offset = 3;
   1802                                     break;
   1803                                 default:
   1804                                     bits_xferred = gspeed * 100 * time_tot;
   1805                                     legend_ndx_offset = 4;
   1806                                 break;
   1807                             }
   1808 
   1809                             if (error_cnt == 0) {
   1810                                 legend_ndx = 0;
   1811                             } else {
   1812                                 rev_ber = bits_xferred / error_cnt;
   1813                                 if (rev_ber == 0) {
   1814                                     legend_ndx = 1;
   1815                                 } else {
   1816                                     legend_ndx = 0;
   1817                                     while (rev_ber > 0) {
   1818                                         rev_ber /= 10;
   1819                                         legend_ndx++;
   1820                                     }
   1821                                     if (legend_ndx > 1) {
   1822                                         legend_ndx =
   1823                                             legend_ndx + legend_ndx_offset - 1;
   1824                                     }
   1825                                 }
   1826                             }
   1827                         }
   1828 
   1829                         /* If exceeds legend size, round legend_ndx down */
   1830                         if (legend_ndx >= nof_legend_low_ber_chars) {
   1831                             legend_ndx = 0;
   1832                         }
   1833                         print_char = legend_low_ber[legend_ndx];
   1834                     } else {
   1835                         if (time_tot == 0) {
   1836                             ber = 0;
   1837                         } else if (error_cnt < (0xffffffff / 1000)) {
   1838                             /* multiplying by 1000 won't cause an overflow */
   1839                             ber = (error_cnt * 1000 / time_tot);
   1840                         } else {
   1841                             /* number is big enough, 
   1842                                so can first divide by time and than multiply */
   1843                             ber = (error_cnt / time_tot * 1000);
   1844                         }
   1845 
   1846                         /* Print matrix entries */
   1847                         if (ber == SRD_EYESCAN_INVALID) {
   1848                            /* print_char = invalid_char; */
   1849                         } else {
   1850 
   1851                             legend_ndx = 0;
   1852                             while (ber > 0) {
   1853                                 ber /= 10;
   1854                                 legend_ndx++;
   1855                             }
   1856 
   1857                             /* If exceeds legend size, round legend_ndx down */
   1858                             if (legend_ndx >= nof_legend_chars) {
   1859                                 legend_ndx = (nof_legend_chars - 1);
   1860                             }
   1861                         }
   1862 
   1863                         print_char = legend[legend_ndx];
   1864                     }
   1865                 }
   1866 
   1867                 cli_out("%c", print_char);
   1868             }
   1869 
   1870             cli_out("|");
   1871 
   1872             /* print description on relevant lines */
   1873             if (pc && pc->phy_id0 == 0x600d && pc->phy_id1 == 0x8500) {
   1874                 if (desc_idx < desc_low_ber_size + desc_size) {
   1875 #if defined(BROADCOM_DEBUG)
   1876                     if (desc_idx < desc_size) {
   1877                         cli_out("%s", description[desc_idx]);
   1878                     } else {
   1879                         cli_out(desc_low_ber[desc_idx - desc_size],
   1880                                 legend_low_ber[desc_idx - desc_size]);
   1881                     }
   1882 #endif
   1883                     desc_idx++;
   1884                 }
   1885             } else {
   1886                 if (desc_idx < desc_ber_size + desc_size) {
   1887 #if defined(BROADCOM_DEBUG)
   1888                     if (desc_idx < desc_size) {
   1889                         cli_out("%s", description[desc_idx]);
   1890                     } else {
   1891                         cli_out(desc_ber[desc_idx - desc_size],
   1892                                 legend[desc_idx - desc_size]);
   1893                     }
   1894 #endif
   1895                     desc_idx++;
   1896                 }
   1897             }
   1898             cli_out("\r\n");
   1899         }
   1900 
   1901         /* print x axis */
   1902         cli_out("    -");
   1903 
   1904         for (hz_i = hz_min; hz_i < hz_max - 9 * sample_res; hz_i++) {
   1905             if (hz_i % sample_res != 0) {
   1906                 continue;
   1907             }
   1908             cli_out("%c",
   1909                     ((((hz_i - hz_min) / sample_res) % 5) ? '-' : '+'));
   1910         }
   1911 
   1912         cli_out("[HORIZONTAL]\r\n");
   1913         cli_out("     ");
   1914 
   1915         for (hz_i = hz_min; hz_i <= hz_max; hz_i++) {
   1916             if (hz_i % sample_res != 0) {
   1917                 continue;
   1918             }
   1919             cli_out("%c",
   1920                     ((((hz_i - hz_min) / sample_res) % 5) ? ' ' : '|'));
   1921         }
   1922 
   1923         cli_out("\r\n");
   1924         cli_out("     ");
   1925         for (hz_i = hz_min; hz_i <= hz_max; hz_i++) {
   1926             if (hz_i % sample_res != 0) {
   1927                 continue;
   1928             }
   1929             if (((hz_i - hz_min) / sample_res) % 5) {
   1930                 cli_out(" ");
   1931             } else {
   1932                 cli_out("%2d", hz_i);
   1933                 sal_sprintf(buf, "%2d", hz_i);
   1934                 hz_i += ((sal_strlen(buf) - 1) * sample_res);
   1935             }
   1936         }
   1937         cli_out("\r\n");
   1938     }
   1939  exit:
   1940     return ret;
   1941 }
   1942 
   1943 cmd_result_t
   1944 _phy_diag_reg(int unit, bcm_pbmp_t pbmp, args_t *args)
   1945 {
   1946     bcm_port_t port, dport;
   1947     int cmd;
   1948     char *cmd_str/*, *core_str*/;
   1949     uint32 *pData, par[5];
   1950     
   1951     par[0] = 0;
   1952     par[1] = 0;
   1953     par[2] = 0;
   1954     par[3] = 0;
   1955     par[4] = 0;
   1956     pData = &par[0];
   1957 
   1958     cmd = PHY_DIAG_CTRL_REG_READ;
   1959 
   1960     if ((cmd_str = ARG_GET(args)) == NULL) {
   1961         return CMD_USAGE;
   1962     }
   1963     if (cmd_str) {
   1964         if (sal_strcasecmp(cmd_str, "core0") == 0) {
   1965             *pData++ = 0;
   1966         } else if (sal_strcasecmp(cmd_str, "core1") == 0) {
   1967             *pData++ = 1;
   1968         } else if (sal_strcasecmp(cmd_str, "core2") == 0) {
   1969             *pData++ = 2;
   1970         } else if (sal_strcasecmp(cmd_str, "mld") == 0) {
   1971             *pData++ = 3;
   1972         }
   1973     }
   1974     if ((cmd_str = ARG_GET(args)) == NULL) { /* Get aer number */
   1975         return CMD_USAGE;
   1976     }
   1977     *pData++ = sal_strtoul(cmd_str, NULL, 0);
   1978 
   1979     if ((cmd_str = ARG_GET(args)) == NULL) { /* Get reg number */
   1980         return CMD_USAGE;
   1981     }
   1982     *pData++ = sal_strtoul(cmd_str, NULL, 0);
   1983 
   1984     if ((cmd_str = ARG_GET(args)) != NULL) { /* Get write data */
   1985         cmd = PHY_DIAG_CTRL_REG_WRITE;
   1986         *pData++ = sal_strtoul(cmd_str, NULL, 0);
   1987     }
   1988 
   1989     /* command targets to Internal serdes device for now */
   1990     /* coverity[overrun-local] */
   1991     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   1992         if (port_diag_ctrl(unit, port, PHY_DIAG_INT,
   1993                                   PHY_DIAG_CTRL_CMD, cmd,
   1994                                   &par) != SOC_E_NONE) {
   1995             return CMD_FAIL;
   1996         }
   1997     }
   1998     return CMD_OK;
   1999 }
   2000 
   2001 cmd_result_t
   2002 _phy_diag_eyescan(int unit, bcm_pbmp_t pbmp, args_t *args)
   2003 {
   2004     int i, speed, port_count;
   2005     cmd_result_t ret = CMD_OK;
   2006     soc_port_phy_eyescan_params_t params;
   2007     soc_port_phy_eyescan_results_t *results;
   2008     int phy_unit, phy_unit_if, phy_unit_value = 0;
   2009     parse_table_t pt;
   2010     int rv, flags = 0;
   2011     uint32 nof_ports;
   2012     uint32 inst;
   2013     char *if_str;
   2014     soc_port_t *ports, port, dport;
   2015     int *local_lane_num, lane_num = 0xff;
   2016     char *eyescan_counters_strs[socPortPhyEyescanNofCounters * 2 + 1];
   2017     char numbers_strs[socPortPhyEyescanNofCounters][3];
   2018 
   2019     for (i = 0; i < socPortPhyEyescanNofCounters; i++) {
   2020         sal_sprintf(numbers_strs[i], "%d", i);
   2021         eyescan_counters_strs[i] = eyescan_counter[i];
   2022         eyescan_counters_strs[socPortPhyEyescanNofCounters + i] =
   2023             numbers_strs[i];
   2024     }
   2025     eyescan_counters_strs[socPortPhyEyescanNofCounters * 2] = NULL;
   2026 
   2027     BCM_PBMP_COUNT(pbmp, port_count);
   2028     if (port_count == 0) {
   2029         return CMD_OK;
   2030     }
   2031 
   2032     results = sal_alloc((port_count) * sizeof(soc_port_phy_eyescan_results_t),
   2033                         "eyescan results array");
   2034     /*array of result per port */
   2035     if (results == NULL) {
   2036         cli_out("ERROR, in phy_diag_eyescan: failed to allocate results");
   2037         return CMD_FAIL;
   2038     }
   2039     ports = sal_alloc((port_count) * sizeof(soc_port_t), "eyescan ports");
   2040     if (ports == NULL) {
   2041         cli_out("ERROR, in phy_diag_eyescan: failed to allocate ports");
   2042         sal_free(results);
   2043         return CMD_FAIL;
   2044     }
   2045     local_lane_num =
   2046         sal_alloc((port_count) * sizeof(int), "eyescan lane_num array");
   2047     if (local_lane_num == NULL) {
   2048         cli_out("ERROR, in phy_diag_eyescan: failed to allocate local_lane_num");
   2049         sal_free(results);
   2050         sal_free(ports);
   2051         return CMD_FAIL;
   2052     }
   2053 
   2054     /*default values */
   2055     params.sample_time = 1000;
   2056     params.sample_resolution = 1;
   2057     params.bounds.horizontal_max = 31;
   2058     params.bounds.horizontal_min = -31;
   2059     params.bounds.vertical_max = 31;
   2060     params.bounds.vertical_min = -31;
   2061     params.counter = socPortPhyEyescanCounterRelativePhy;
   2062     params.error_threshold = 20;
   2063     params.time_upper_bound = 256000;
   2064     params.type = -1;
   2065     /* defaults for BER projection */
   2066     params.ber_proj_scan_mode = 0;  /* DIAG_BER_VERT DIAG_BER_POS */
   2067     params.ber_proj_timer_cnt = 96;
   2068     params.ber_proj_err_cnt = 8;
   2069 
   2070     sal_memset(results, 0, sizeof(soc_port_phy_eyescan_results_t) * port_count);
   2071 
   2072     nof_ports = 0;
   2073     /* coverity[overrun-local] */
   2074     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   2075         ports[nof_ports] = port;
   2076         nof_ports++;
   2077     }
   2078 
   2079     params.nof_threshold_links = nof_ports / 2;
   2080     if (params.nof_threshold_links < 1) {
   2081         params.nof_threshold_links = 1;
   2082     }
   2083 
   2084     parse_table_init(unit, &pt);
   2085     parse_table_add(&pt, "type", PQ_DFL | PQ_INT, (void *)(0),
   2086                     &(params.type), NULL);
   2087     parse_table_add(&pt, "vertical_max", PQ_DFL | PQ_INT, (void *)(0),
   2088                     &(params.bounds.vertical_max), NULL);
   2089     parse_table_add(&pt, "vertical_min", PQ_DFL | PQ_INT, (void *)(0),
   2090                     &(params.bounds.vertical_min), NULL);
   2091     parse_table_add(&pt, "horizontal_max", PQ_DFL | PQ_INT, (void *)(0),
   2092                     &(params.bounds.horizontal_max), NULL);
   2093     parse_table_add(&pt, "horizontal_min", PQ_DFL | PQ_INT, (void *)(0),
   2094                     &(params.bounds.horizontal_min), NULL);
   2095     parse_table_add(&pt, "sample_resolution", PQ_DFL | PQ_INT, (void *)(0),
   2096                     &(params.sample_resolution), NULL);
   2097     parse_table_add(&pt, "sample_time", PQ_DFL | PQ_INT, (void *)(0),
   2098                     &(params.sample_time), NULL);
   2099     parse_table_add(&pt, "counter", PQ_MULTI | PQ_DFL | PQ_NO_EQ_OPT,
   2100                     (void *)(0), &(params.counter), &eyescan_counters_strs);
   2101     parse_table_add(&pt, "flags", PQ_DFL | PQ_INT, (void *)(0), &flags, NULL);
   2102     parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0), &lane_num, NULL);
   2103     parse_table_add(&pt, "error_threshold", PQ_DFL | PQ_INT, (void *)(0),
   2104                     &(params.error_threshold), NULL);
   2105     parse_table_add(&pt, "time_upper_bound", PQ_DFL | PQ_INT, (void *)(0),
   2106                     &(params.time_upper_bound), NULL);
   2107     parse_table_add(&pt, "nof_threshold_links", PQ_DFL | PQ_INT, (void *)(0),
   2108                     &(params.nof_threshold_links), NULL);
   2109     parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0),
   2110                     &phy_unit_value, NULL);
   2111     parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL);
   2112     /* BER projection related parameter */
   2113     parse_table_add(&pt, "ber_scan_mode", PQ_DFL | PQ_INT, (void *)(0),
   2114                     &(params.ber_proj_scan_mode), NULL);
   2115     parse_table_add(&pt, "timer_control", PQ_DFL | PQ_INT, (void *)(0),
   2116                     &(params.ber_proj_timer_cnt), NULL);
   2117     parse_table_add(&pt, "max_err_control", PQ_DFL | PQ_INT, (void *)(0),
   2118                     &(params.ber_proj_err_cnt), NULL);
   2119 
   2120     if (parse_arg_eq(args, &pt) < 0) {
   2121         cli_out("ERROR: could not parse parameters\n");
   2122         parse_arg_eq_done(&pt);
   2123         ret = CMD_FAIL;
   2124         goto exit;
   2125     }
   2126 
   2127     if (ARG_CNT(args) > 0) {
   2128         cli_out("%s: Unknown argument %s\n", ARG_CMD(args), ARG_CUR(args));
   2129         parse_arg_eq_done(&pt);
   2130         ret = CMD_FAIL;
   2131         goto exit;
   2132     }
   2133     params.counter = params.counter % socPortPhyEyescanNofCounters;
   2134     if(params.type == -1) {  /* -1 is un-specified, so set to 1 as default */
   2135         params.type = 1 ;    
   2136     }                        /*  params.type !=0 means phymod eyescan      */
   2137 
   2138     phy_unit = 0;
   2139     rv = _phy_diag_phy_if_get(if_str, &phy_unit_if);
   2140     if (rv != ((int)CMD_OK)) {
   2141         parse_arg_eq_done(&pt);
   2142         ret = CMD_FAIL;
   2143         goto exit;
   2144     }
   2145     rv = _phy_diag_phy_unit_get(phy_unit_value, &phy_unit);
   2146     if (rv != ((int)CMD_OK)) {
   2147         parse_arg_eq_done(&pt);
   2148         ret = CMD_FAIL;
   2149         goto exit;
   2150     }
   2151 
   2152     /* inst has unit, intf, lane */
   2153     inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if,
   2154                              lane_num == 0xff ? PHY_DIAG_LN_DFLT : lane_num);
   2155 
   2156     for (i = 0; i < nof_ports; i++) {
   2157         results[i].ext_done = 0;
   2158     }
   2159 
   2160     if (lane_num == 0xff) {
   2161         if (local_lane_num != NULL) {
   2162             sal_free(local_lane_num);
   2163         }
   2164         local_lane_num = NULL;
   2165     } else {
   2166             /*now check the correct lane num input for each port */
   2167 #ifndef PORTMOD_SUPPORT
   2168         for (i = 0; i < nof_ports; i++) {                
   2169             if (lane_num > SOC_INFO(unit).port_num_lanes[ports[i]]) {
   2170                 cli_out("ERROR, in phy_diag_eyescan: lane num is wrong \n");
   2171                 return CMD_FAIL;
   2172             }
   2173         }
   2174 #endif
   2175 
   2176         for(i = 0; i < port_count; i++) {
   2177             sal_memcpy(&local_lane_num[i], &lane_num, sizeof(int));
   2178         }
   2179     }
   2180 
   2181     if ((params.sample_time < 0) || (params.sample_time > params.time_upper_bound)) {
   2182         cli_out("ERROR, in phy_diag_eyescan: sample time %d"
   2183                 " out of range ( 0 ~ %d )\n",
   2184                 params.sample_time, params.time_upper_bound);
   2185         ret = CMD_FAIL;
   2186         goto exit;
   2187     }
   2188 
   2189     rv = soc_port_phy_eyescan_run(unit, inst, flags, &params, nof_ports, ports,
   2190                                   local_lane_num, results);
   2191 #ifdef PHYMOD_SUPPORT
   2192     if (!(is_eyescan_algorithm_legacy_mode(unit, nof_ports, ports, inst)) || rv){
   2193         ret = (rv == SOC_E_NONE)? CMD_OK : CMD_FAIL;
   2194         goto exit;
   2195     }
   2196 #endif
   2197 
   2198 #ifdef PHYMOD_SUPPORT
   2199     if(is_eyescan_algorithm_legacy_rpt_mode(unit, nof_ports, ports, inst))
   2200 #endif 
   2201     {
   2202         rv = soc_port_phy_eyescan_extrapolate(unit, flags, &params, nof_ports,
   2203                                               ports, results);
   2204 
   2205         if (rv != SOC_E_NONE) {
   2206             ret = CMD_FAIL;
   2207             goto exit;
   2208         }
   2209 
   2210         for (i = 0; i < nof_ports; i++) {
   2211 
   2212             rv = bcm_port_speed_get(unit, ports[i], &speed);
   2213             if (rv != SOC_E_NONE) {
   2214                 ret = CMD_FAIL;
   2215                 goto exit;
   2216             }
   2217 
   2218             cli_out("Eye\\Cross-section Results For Port %d (with rate %d):\n",
   2219                     ports[i], speed);
   2220 
   2221             rv = _phy_diag_eyescan_res_print(unit, speed, ports[i],
   2222                                              params.sample_resolution,
   2223                                              &(params.bounds), &(results[i]));
   2224 
   2225             if (rv != SOC_E_NONE) {
   2226                 ret = CMD_FAIL;
   2227                 goto exit;
   2228             }
   2229         }
   2230     }
   2231     ret = CMD_OK;
   2232 
   2233  exit:
   2234     if (results != NULL) {
   2235         sal_free(results);
   2236     }
   2237     if (ports != NULL) {
   2238         sal_free(ports);
   2239     }
   2240     if (local_lane_num != NULL) {
   2241         sal_free(local_lane_num);
   2242     }
   2243     return ret;
   2244 }
   2245 
   2246 cmd_result_t
   2247 _phy_diag_berproj(int unit, bcm_pbmp_t pbmp, args_t *args)
   2248 {
   2249     parse_table_t pt;
   2250     bcm_port_t port, dport;
   2251     int num_ports, i, num_lanes;
   2252     cmd_result_t res = CMD_OK;
   2253     bcm_error_t rv = BCM_E_NONE;
   2254     char *if_str;
   2255     int phy_unit, phy_unit_value = 0, phy_unit_if;
   2256     uint32 inst;
   2257     soc_port_phy_ber_proj_params_t params;
   2258     soc_phy_prbs_errcnt_t** prbs_errcnt = NULL;
   2259     uint32 time_remaining;
   2260 
   2261     params.ber_proj_fec_type = _SHR_PORT_PHY_FEC_RS_544;
   2262     params.ber_proj_hist_errcnt_thresh = 0;
   2263     params.ber_proj_timeout_s = 60;
   2264 
   2265     /*
   2266      * unit:  phy_unit_value: phy chain number
   2267      * if  :  if_str="sys"|"line"
   2268      */
   2269     parse_table_init(unit, &pt);
   2270 
   2271     parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0),
   2272                     &phy_unit_value, NULL);
   2273     parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL);
   2274     parse_table_add(&pt, "hist_errcnt_threshold", PQ_DFL | PQ_INT, (void *)(0),
   2275                     &params.ber_proj_hist_errcnt_thresh, NULL);
   2276     parse_table_add(&pt, "sample_time", PQ_DFL | PQ_INT, (void *)(0),
   2277                     &params.ber_proj_timeout_s, NULL);
   2278 
   2279     if (parse_arg_eq(args, &pt) < 0) {
   2280         cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   2281         parse_arg_eq_done(&pt);
   2282         return CMD_USAGE;
   2283     }
   2284 
   2285     res = _phy_diag_phy_if_get(if_str, &phy_unit_if);
   2286     if (res == CMD_OK) {
   2287         res = _phy_diag_phy_unit_get(phy_unit_value, &phy_unit);
   2288     }
   2289 
   2290     /* Now free allocated strings */
   2291     parse_arg_eq_done(&pt);
   2292 
   2293     if (res != CMD_OK) {
   2294         return res;
   2295     }
   2296 
   2297     inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, PHY_DIAG_LN_DFLT);
   2298 
   2299     /* Here we parallelize the ber proj for all the ports
   2300      * Here're the steps for ber proj:
   2301      * 1. Pre: allocate memory to store err count.
   2302      * 2. Pre config analyzer. (Only needed when hist_errcnt_threshold == 0.)
   2303      * 3. Config: Configure BER analyzer.
   2304      * 4. Start: Start accumulating errors.
   2305      * 5. Collect: Collect error count.
   2306      * 6. Proj: Project BER.
   2307      * 7. Print output.
   2308      */
   2309 
   2310     /* Verify input */
   2311     if (params.ber_proj_timeout_s <= 0) {
   2312         cli_out("Error: invalid timeout value: %d\n", params.ber_proj_timeout_s);
   2313         return CMD_USAGE;
   2314     }
   2315 
   2316     num_ports = 0;
   2317     /* coverity[overrun-local] */
   2318     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   2319         num_ports++;
   2320     }
   2321 
   2322     /* Allocate memories to collect error count */
   2323     prbs_errcnt = sal_alloc(sizeof(soc_phy_prbs_errcnt_t*)*num_ports, "BER error cnt array");
   2324     if (prbs_errcnt == NULL) {
   2325         cli_out("Insufficient memory.\n");
   2326         res = CMD_FAIL;
   2327         goto exit;
   2328     }
   2329     /* Initialize memory space */
   2330     for (i = 0; i < num_ports; i++) {
   2331         prbs_errcnt[i] = NULL;
   2332     }
   2333 
   2334     i = 0;
   2335     /* coverity[overrun-local] */
   2336     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   2337         num_lanes = SOC_INFO(unit).port_num_lanes[port];
   2338         prbs_errcnt[i] = sal_alloc(sizeof(soc_phy_prbs_errcnt_t)*num_lanes, "BER error cnt");
   2339         if (prbs_errcnt[i] == NULL) {
   2340             cli_out("Insufficient memory.\n");
   2341             res = CMD_FAIL;
   2342             goto exit;
   2343         }
   2344         sal_memset(prbs_errcnt[i], 0, sizeof(soc_phy_prbs_errcnt_t)*num_lanes);
   2345         i++;
   2346     }
   2347 
   2348     if (params.ber_proj_hist_errcnt_thresh == 0) {
   2349         /* Pre-stage, only needed when using optimized errcnt threshold. */
   2350         cli_out("Getting optimized threshold for all the lanes...\n");
   2351         i = 0;
   2352         /* coverity[overrun-local] */
   2353         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   2354             params.ber_proj_phase = SOC_PORT_PHY_BER_PROJ_P_PRE;
   2355             params.ber_proj_prbs_errcnt = prbs_errcnt[i];
   2356             rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD,
   2357                                  PHY_DIAG_CTRL_BER_PROJ, (void *)&params);
   2358             if (rv != BCM_E_NONE) {
   2359                 res = CMD_FAIL;
   2360                 goto exit;
   2361             }
   2362             i++;
   2363         }
   2364         /* 99 is used to generate CEIL function of 5% of timeout_s */
   2365         time_remaining = (params.ber_proj_timeout_s * 5 + 99)/ 100;
   2366         sal_sleep(time_remaining);
   2367     }
   2368 
   2369     i = 0;
   2370     /* coverity[overrun-local] */
   2371     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   2372         /* Stage 1: Config PRBS checker */
   2373         params.ber_proj_phase = SOC_PORT_PHY_BER_PROJ_P_CONFIG;
   2374         params.ber_proj_prbs_errcnt = prbs_errcnt[i];
   2375         rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD,
   2376                              PHY_DIAG_CTRL_BER_PROJ, (void *)&params);
   2377         if (rv != BCM_E_NONE) {
   2378             res = CMD_FAIL;
   2379             goto exit;
   2380         }
   2381         i++;
   2382     }
   2383 
   2384     i = 0;
   2385     /* coverity[overrun-local] */
   2386     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   2387         /* Stage 2: Start Error accumulation */
   2388         params.ber_proj_phase = SOC_PORT_PHY_BER_PROJ_P_START;
   2389         params.ber_proj_prbs_errcnt = prbs_errcnt[i];
   2390         rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD,
   2391                              PHY_DIAG_CTRL_BER_PROJ, (void *)&params);
   2392         if (rv != BCM_E_NONE) {
   2393             res = CMD_FAIL;
   2394             goto exit;
   2395         }
   2396         i++;
   2397     }
   2398 
   2399     /* Stage 3: Collect PRBS error count */
   2400     time_remaining = params.ber_proj_timeout_s;
   2401     while (time_remaining > 0) {
   2402         if (time_remaining > 5) {
   2403             sal_sleep(5);
   2404             time_remaining = time_remaining - 5;
   2405             cli_out(".");
   2406         } else {
   2407             sal_sleep(time_remaining);
   2408             time_remaining = 0;
   2409             cli_out(".\n");
   2410         }
   2411         i = 0;
   2412         /* coverity[overrun-local] */
   2413         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   2414             params.ber_proj_phase = SOC_PORT_PHY_BER_PROJ_P_COLLECT;
   2415             params.ber_proj_prbs_errcnt = prbs_errcnt[i];
   2416             rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD,
   2417                                  PHY_DIAG_CTRL_BER_PROJ, (void *)&params);
   2418             if (rv != BCM_E_NONE) {
   2419                 res = CMD_FAIL;
   2420                 goto exit;
   2421             }
   2422             i++;
   2423         }
   2424     }
   2425 
   2426     /* Stage 4: BER Calculate */
   2427     i = 0;
   2428     /* coverity[overrun-local] */
   2429     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   2430         params.ber_proj_phase = SOC_PORT_PHY_BER_PROJ_P_CALC;
   2431         params.ber_proj_prbs_errcnt = prbs_errcnt[i];
   2432         rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD,
   2433                              PHY_DIAG_CTRL_BER_PROJ, (void *)&params);
   2434         if (rv != BCM_E_NONE) {
   2435             res = CMD_FAIL;
   2436             goto exit;
   2437         }
   2438         i++;
   2439     }
   2440 
   2441 exit:
   2442     if (prbs_errcnt != NULL) {
   2443         i = 0;
   2444         /* coverity[overrun-local] */
   2445         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   2446             if (prbs_errcnt[i] != NULL) {
   2447                 sal_free(prbs_errcnt[i]);
   2448             }
   2449             i++;
   2450         }
   2451         sal_free(prbs_errcnt);
   2452     }
   2453 
   2454     return res;
   2455 }
   2456 
   2457 #ifdef PORTMOD_SUPPORT
   2458 
   2459 int portmod_port_num_phys_get(int unit, int port, int *nof_phys)
   2460 {
   2461 int is_most_ext = 0;
   2462 int phyn,  nof_cores;
   2463 phymod_core_access_t core_access[7];
   2464 int rv;
   2465     phyn = 0;
   2466 
   2467     while (!is_most_ext) {
   2468         rv = portmod_port_core_access_get(unit, port, phyn, MAX_PHYN, core_access, &nof_cores, &is_most_ext);
   2469         if (BCM_FAILURE(rv)){
   2470             return CMD_FAIL;
   2471         }
   2472         phyn++;
   2473     }
   2474     *nof_phys = phyn;
   2475     return CMD_OK;
   2476 
   2477 }
   2478 #endif
   2479 
   2480 int
   2481 port_to_phyaddr(int unit, int port)
   2482 {
   2483     int phy_id;
   2484 #ifdef PORTMOD_SUPPORT
   2485     if (soc_feature(unit, soc_feature_portmod)) {
   2486         phy_id = portmod_port_to_phyaddr(unit, port);
   2487     } else
   2488 #endif
   2489     {
   2490         phy_id = PORT_TO_PHY_ADDR(unit, port);
   2491     }
   2492     return phy_id;
   2493 }
   2494 
   2495 int
   2496 port_to_phyaddr_int(int unit, int port)
   2497 {
   2498     int phy_id;
   2499 #ifdef PORTMOD_SUPPORT
   2500     if (soc_feature(unit, soc_feature_portmod)) {
   2501         phy_id = portmod_port_to_phyaddr_int(unit, port);
   2502     } else
   2503 #endif
   2504     {
   2505         phy_id = PORT_TO_PHY_ADDR_INT(unit, port);
   2506     }
   2507     return phy_id;
   2508 }
   2509 
   2510 void
   2511 _print_timesync_egress_message_mode(char *message,
   2512                                          bcm_port_phy_timesync_event_message_egress_mode_t
   2513                                          mode)
   2514 {
   2515 
   2516     cli_out("%s (no,uc,rc,ct) - ", message);
   2517 
   2518     switch (mode) {
   2519         case bcmPortPhyTimesyncEventMessageEgressModeNone:
   2520             cli_out("NOne\n");
   2521             break;
   2522         case bcmPortPhyTimesyncEventMessageEgressModeUpdateCorrectionField:
   2523             cli_out("Update_Correctionfield\n");
   2524             break;
   2525         case bcmPortPhyTimesyncEventMessageEgressModeReplaceCorrectionFieldOrigin:
   2526             cli_out("Replace_Correctionfield_origin\n");
   2527             break;
   2528         case bcmPortPhyTimesyncEventMessageEgressModeCaptureTimestamp:
   2529             cli_out("Capture_Timestamp\n");
   2530             break;
   2531         default:
   2532             cli_out("\n");
   2533             break;
   2534     }
   2535 
   2536 }
   2537 
   2538 void
   2539 _print_inband_timesync_matching_criterion(uint32 flags)
   2540 {
   2541     uint8 delimit = 0;
   2542     cli_out("InBand timesync MATch (none, ip, mac, pnum, vlid) - ");
   2543 
   2544     if (flags & BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR) {
   2545         cli_out("ip");
   2546         delimit = 1;
   2547     }
   2548     if (flags & BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_MAC_ADDR) {
   2549         cli_out("%s", delimit ? ", mac" : "mac");
   2550         delimit = 1;
   2551     }
   2552     if (flags & BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_SRC_PORT_NUM) {
   2553         cli_out("%s", delimit ? ", pnum" : "pnum");
   2554         delimit = 1;
   2555     }
   2556     if (flags & BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID) {
   2557         cli_out("%s", delimit ? ", vlid" : "vlid");
   2558     }
   2559     cli_out("\n");
   2560 }
   2561 
   2562 bcm_port_phy_timesync_event_message_egress_mode_t
   2563 _convert_timesync_egress_message_str(char *str,
   2564                                      bcm_port_phy_timesync_event_message_egress_mode_t
   2565                                      def)
   2566 {
   2567     int i;
   2568     struct s_array {
   2569         char *s;
   2570         bcm_port_phy_timesync_event_message_egress_mode_t value;
   2571     } data[] = {
   2572         {
   2573         "no", bcmPortPhyTimesyncEventMessageEgressModeNone}, {
   2574         "uc", bcmPortPhyTimesyncEventMessageEgressModeUpdateCorrectionField}, {
   2575         "rc",
   2576                 bcmPortPhyTimesyncEventMessageEgressModeReplaceCorrectionFieldOrigin},
   2577         {
   2578     "ct", bcmPortPhyTimesyncEventMessageEgressModeCaptureTimestamp}};
   2579 
   2580     for (i = 0; i < (sizeof(data) / sizeof(data[0])); i++) {
   2581         if (!sal_strncmp(str, data[i].s, 2)) {
   2582             return data[i].value;
   2583         }
   2584     }
   2585     return def;
   2586 }
   2587 
   2588 void
   2589 _print_timesync_ingress_message_mode(char *message,
   2590                                           bcm_port_phy_timesync_event_message_ingress_mode_t
   2591                                           mode)
   2592 {
   2593 
   2594     cli_out("%s (no,uc,it,id) - ", message);
   2595 
   2596     switch (mode) {
   2597         case bcmPortPhyTimesyncEventMessageIngressModeNone:
   2598             cli_out("NOne\n");
   2599             break;
   2600         case bcmPortPhyTimesyncEventMessageIngressModeUpdateCorrectionField:
   2601             cli_out("Update_Correctionfield\n");
   2602             break;
   2603         case bcmPortPhyTimesyncEventMessageIngressModeInsertTimestamp:
   2604             cli_out("Insert_Timestamp\n");
   2605             break;
   2606         case bcmPortPhyTimesyncEventMessageIngressModeInsertDelaytime:
   2607             cli_out("Insert_Delaytime\n");
   2608             break;
   2609         default:
   2610             cli_out("\n");
   2611             break;
   2612     }
   2613 
   2614 }
   2615 
   2616 bcm_port_phy_timesync_event_message_ingress_mode_t
   2617 _convert_timesync_ingress_message_str(char *str,
   2618                                       bcm_port_phy_timesync_event_message_ingress_mode_t
   2619                                       def)
   2620 {
   2621     int i;
   2622     struct s_array {
   2623         char *s;
   2624         bcm_port_phy_timesync_event_message_ingress_mode_t value;
   2625     } data[] = {
   2626         {
   2627         "no", bcmPortPhyTimesyncEventMessageIngressModeNone}, {
   2628         "uc", bcmPortPhyTimesyncEventMessageIngressModeUpdateCorrectionField}, {
   2629         "it", bcmPortPhyTimesyncEventMessageIngressModeInsertTimestamp}, {
   2630     "id", bcmPortPhyTimesyncEventMessageIngressModeInsertDelaytime}};
   2631 
   2632     for (i = 0; i < (sizeof(data) / sizeof(data[0])); i++) {
   2633         if (!sal_strncmp(str, data[i].s, 2)) {
   2634             return data[i].value;
   2635         }
   2636     }
   2637     return def;
   2638 }
   2639 
   2640 void
   2641 _print_timesync_gmode(char *message,
   2642                            bcm_port_phy_timesync_global_mode_t mode)
   2643 {
   2644 
   2645     cli_out("%s (fr,si,cp) - ", message);
   2646 
   2647     switch (mode) {
   2648         case bcmPortPhyTimesyncModeFree:
   2649             cli_out("FRee\n");
   2650             break;
   2651         case bcmPortPhyTimesyncModeSyncin:
   2652             cli_out("SyncIn\n");
   2653             break;
   2654         case bcmPortPhyTimesyncModeCpu:
   2655             cli_out("CPu\n");
   2656             break;
   2657         default:
   2658             cli_out("\n");
   2659             break;
   2660     }
   2661 
   2662 }
   2663 
   2664 bcm_port_phy_timesync_global_mode_t
   2665 _convert_timesync_gmode_str(char *str,
   2666                                  bcm_port_phy_timesync_global_mode_t def)
   2667 {
   2668     int i;
   2669     struct s_array {
   2670         char *s;
   2671         bcm_port_phy_timesync_global_mode_t value;
   2672     } data[] = {
   2673         {
   2674         "fr", bcmPortPhyTimesyncModeFree}, {
   2675         "si", bcmPortPhyTimesyncModeSyncin}, {
   2676     "cp", bcmPortPhyTimesyncModeCpu}};
   2677 
   2678     for (i = 0; i < (sizeof(data) / sizeof(data[0])); i++) {
   2679         if (!sal_strncmp(str, data[i].s, 2)) {
   2680             return data[i].value;
   2681         }
   2682     }
   2683     return def;
   2684 }
   2685 
   2686 void
   2687 _print_framesync_mode(char *message,
   2688                            bcm_port_phy_timesync_framesync_mode_t mode)
   2689 {
   2690 
   2691     cli_out("%s (fno,fs0,fs1,fss,fsc) - ", message);
   2692 
   2693     switch (mode) {
   2694         case bcmPortPhyTimesyncFramesyncNone:
   2695             cli_out("FramesyncNOne\n");
   2696             break;
   2697         case bcmPortPhyTimesyncFramesyncSyncin0:
   2698             cli_out("FramesyncSyncIn0\n");
   2699             break;
   2700         case bcmPortPhyTimesyncFramesyncSyncin1:
   2701             cli_out("FramesyncSyncIn1\n");
   2702             break;
   2703         case bcmPortPhyTimesyncFramesyncSyncout:
   2704             cli_out("FrameSyncSyncout\n");
   2705             break;
   2706         case bcmPortPhyTimesyncFramesyncCpu:
   2707             cli_out("FrameSyncCpu\n");
   2708             break;
   2709         default:
   2710             cli_out("\n");
   2711             break;
   2712     }
   2713 
   2714 }
   2715 
   2716 bcm_port_phy_timesync_framesync_mode_t
   2717 _convert_framesync_mode_str(char *str,
   2718                                  bcm_port_phy_timesync_framesync_mode_t def)
   2719 {
   2720     int i;
   2721     struct s_array {
   2722         char *s;
   2723         bcm_port_phy_timesync_framesync_mode_t value;
   2724     } data[] = {
   2725         {
   2726         "fno", bcmPortPhyTimesyncFramesyncNone}, {
   2727         "fs0", bcmPortPhyTimesyncFramesyncSyncin0}, {
   2728         "fs1", bcmPortPhyTimesyncFramesyncSyncin1}, {
   2729         "fss", bcmPortPhyTimesyncFramesyncSyncout}, {
   2730     "fsc", bcmPortPhyTimesyncFramesyncCpu}};
   2731 
   2732     for (i = 0; i < (sizeof(data) / sizeof(data[0])); i++) {
   2733         if (!sal_strncmp(str, data[i].s, 3)) {
   2734             return data[i].value;
   2735         }
   2736     }
   2737     return def;
   2738 }
   2739 
   2740 void
   2741 _print_syncout_mode(char *message,
   2742                          bcm_port_phy_timesync_syncout_mode_t mode)
   2743 {
   2744 
   2745     cli_out("%s (sod,sot,spt,sps) - ", message);
   2746 
   2747     switch (mode) {
   2748         case bcmPortPhyTimesyncSyncoutDisable:
   2749             cli_out("SyncOutDisable\n");
   2750             break;
   2751         case bcmPortPhyTimesyncSyncoutOneTime:
   2752             cli_out("SyncoutOneTime\n");
   2753             break;
   2754         case bcmPortPhyTimesyncSyncoutPulseTrain:
   2755             cli_out("SyncoutPulseTrain\n");
   2756             break;
   2757         case bcmPortPhyTimesyncSyncoutPulseTrainWithSync:
   2758             cli_out("SyncoutPulsetrainSync\n");
   2759             break;
   2760         default:
   2761             cli_out("\n");
   2762             break;
   2763     }
   2764 
   2765 }
   2766 
   2767 bcm_port_phy_timesync_syncout_mode_t
   2768 _convert_syncout_mode_str(char *str,
   2769                                bcm_port_phy_timesync_syncout_mode_t def)
   2770 {
   2771     int i;
   2772     struct s_array {
   2773         char *s;
   2774         bcm_port_phy_timesync_syncout_mode_t value;
   2775     } data[] = {
   2776         {
   2777         "sod", bcmPortPhyTimesyncSyncoutDisable}, {
   2778         "sot", bcmPortPhyTimesyncSyncoutOneTime}, {
   2779         "spt", bcmPortPhyTimesyncSyncoutPulseTrain}, {
   2780     "sps", bcmPortPhyTimesyncSyncoutPulseTrainWithSync}};
   2781 
   2782     for (i = 0; i < (sizeof(data) / sizeof(data[0])); i++) {
   2783         if (!sal_strncmp(str, data[i].s, 3)) {
   2784             return data[i].value;
   2785         }
   2786     }
   2787     return def;
   2788 }
   2789 
   2790 void
   2791 _set_inband_timesync_matching_criterion(char *str,
   2792                                         uint32 * inband_ctrl_flags)
   2793 {
   2794     int i;
   2795     struct s_array {
   2796         char *s;
   2797         uint32 flag;
   2798     } data[] = {
   2799                   {"ip"  , BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR},
   2800                   {"mac" , BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_MAC_ADDR},
   2801                   {"pnum", BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_SRC_PORT_NUM},
   2802                   {"vlid", BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID},
   2803                   {"none", 0}
   2804                };
   2805 
   2806     *inband_ctrl_flags &=
   2807                 ~(BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR |
   2808                   BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_MAC_ADDR |
   2809                   BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_SRC_PORT_NUM |
   2810                   BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID);
   2811     for ( i = 0; i < (sizeof(data) / sizeof(data[0])); i++ ) {
   2812         if ( ! sal_strcmp(str, data[i].s) ) {
   2813             *inband_ctrl_flags |= data[i].flag;
   2814         }
   2815     }
   2816 
   2817 }
   2818 
   2819 void
   2820 _print_timesync_config(bcm_port_phy_timesync_config_t *conf)
   2821 {
   2822 
   2823     cli_out("ENable (Y or N) - %s\n",
   2824             conf->flags & BCM_PORT_PHY_TIMESYNC_ENABLE ? "Yes" : "No");
   2825 
   2826     cli_out("CaptureTS (Y or N) - %s\n",
   2827             conf->
   2828             flags & BCM_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE ? "Yes" : "No");
   2829 
   2830     cli_out("HeartbeatTS (Y or N) - %s\n",
   2831             conf->
   2832             flags & BCM_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE ? "Yes" : "No");
   2833 
   2834     cli_out("RxCrc (Y or N) - %s\n",
   2835             conf->flags & BCM_PORT_PHY_TIMESYNC_RX_CRC_ENABLE ? "Yes" : "No");
   2836 
   2837     cli_out("AS (Y or N) - %s\n",
   2838             conf->flags & BCM_PORT_PHY_TIMESYNC_8021AS_ENABLE ? "Yes" : "No");
   2839 
   2840     cli_out("L2 (Y or N) - %s\n",
   2841             conf->flags & BCM_PORT_PHY_TIMESYNC_L2_ENABLE ? "Yes" : "No");
   2842 
   2843     cli_out("IP4 (Y or N) - %s\n",
   2844             conf->flags & BCM_PORT_PHY_TIMESYNC_IP4_ENABLE ? "Yes" : "No");
   2845 
   2846     cli_out("IP6 (Y or N) - %s\n",
   2847             conf->flags & BCM_PORT_PHY_TIMESYNC_IP6_ENABLE ? "Yes" : "No");
   2848 
   2849     cli_out("ExtClock (Y or N) - %s\n",
   2850             conf->flags & BCM_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT ? "Yes" : "No");
   2851 
   2852     cli_out("ITpid = 0x%04x\n", conf->itpid);
   2853 
   2854     cli_out("OTpid = 0x%04x\n", conf->otpid);
   2855 
   2856     cli_out("OriginalTimecodeSeconds = 0x%08x%08x\n",
   2857             COMPILER_64_HI(conf->original_timecode.seconds),
   2858             COMPILER_64_LO(conf->original_timecode.seconds));
   2859 
   2860     cli_out("OriginalTimecodeNanoseconds = 0x%08x\n",
   2861             conf->original_timecode.nanoseconds);
   2862 
   2863     _print_timesync_gmode("GMode", conf->gmode);
   2864 
   2865     _print_framesync_mode("FramesyncMode", conf->framesync.mode);
   2866 
   2867     _print_syncout_mode("SyncoutMode", conf->syncout.mode);
   2868 
   2869     cli_out("TxOffset = %d\n", conf->tx_timestamp_offset);
   2870 
   2871     cli_out("RxOffset = %d\n", conf->rx_timestamp_offset);
   2872 
   2873     _print_timesync_egress_message_mode("TxSync", conf->tx_sync_mode);
   2874     _print_timesync_egress_message_mode("TxDelayReq",
   2875                                         conf->tx_delay_request_mode);
   2876     _print_timesync_egress_message_mode("TxPdelayReq",
   2877                                         conf->tx_pdelay_request_mode);
   2878     _print_timesync_egress_message_mode("TxPdelayreS",
   2879                                         conf->tx_pdelay_response_mode);
   2880 
   2881     _print_timesync_ingress_message_mode("RxSync", conf->rx_sync_mode);
   2882     _print_timesync_ingress_message_mode("RxDelayReq",
   2883                                          conf->rx_delay_request_mode);
   2884     _print_timesync_ingress_message_mode("RxPdelayReq",
   2885                                          conf->rx_pdelay_request_mode);
   2886     _print_timesync_ingress_message_mode("RxPdelayreS",
   2887                                          conf->rx_pdelay_response_mode);
   2888 
   2889 }
   2890 
   2891 void
   2892 _print_inband_timesync_config(bcm_port_phy_timesync_config_t *conf)
   2893 {
   2894     cli_out("InBand timesync message Sync (Y or N)    - %s\n",
   2895             ( conf->inband_control.flags
   2896                    &  BCM_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE )
   2897                    ? "Yes" : "No");
   2898     cli_out("InBand timesync Delay Request (Y or N)   - %s\n",
   2899             ( conf->inband_control.flags
   2900                    &  BCM_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE )
   2901                    ? "Yes" : "No");
   2902     cli_out("InBand timesync Pdelay Request (Y or N)  - %s\n",
   2903             ( conf->inband_control.flags
   2904                    &  BCM_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE )
   2905                    ? "Yes" : "No");
   2906     cli_out("InBand timesync Pdelay reSponse (Y or N) - %s\n",
   2907             ( conf->inband_control.flags
   2908                    &  BCM_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE )
   2909                    ? "Yes" : "No");
   2910     cli_out("InBand timesync ID (Resv_0) - 0x%X\n",
   2911               conf->inband_control.resv0_id);
   2912     cli_out("InBand timesync ID ChecK (Y or N)  - %s\n",
   2913             ( conf->inband_control.flags
   2914                    &  BCM_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK )
   2915                    ? "Yes" : "No");
   2916     cli_out("InBand timesync ID Update (Y or N) - %s\n",
   2917             ( conf->inband_control.flags
   2918                    &  BCM_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE )
   2919                    ? "Yes" : "No");
   2920     _print_inband_timesync_matching_criterion(conf->inband_control.flags);
   2921 
   2922     cli_out("InBand timesync Follow Up Assist (Y or N) - %s\n",
   2923             ( conf->inband_control.flags
   2924                    &  BCM_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST )
   2925                    ? "Yes" : "No");
   2926     cli_out("InBand timesync Delay Response Assist (Y or N) - %s\n",
   2927             ( conf->inband_control.flags
   2928                    &  BCM_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST )
   2929                    ? "Yes" : "No");
   2930     cli_out("InBand timesync Long TimeStamp (Y or N) - %s\n",
   2931             ( conf->inband_control.timer_mode
   2932                    &  bcmPortPhyTimesyncTimerMode80bit )
   2933                    ? "Yes" : "No");
   2934 }
   2935 
   2936 void
   2937 _print_heartbeat_ts(int unit, bcm_port_t port)
   2938 {
   2939     int rv;
   2940     uint64 time;
   2941 
   2942     rv = bcm_port_control_phy_timesync_get(unit, port,
   2943                                            bcmPortControlPhyTimesyncHeartbeatTimestamp,
   2944                                            &time);
   2945 
   2946     if (rv != BCM_E_NONE) {
   2947         cli_out("bcm_port_control_phy_timesync_get "
   2948                 "failed with error  u=%d p=%d %s\n",
   2949                 unit, port, bcm_errmsg(rv));
   2950     }
   2951 
   2952     cli_out("Heartbeat TS = %08x%08x\n",
   2953             COMPILER_64_HI(time), COMPILER_64_LO(time));
   2954 }
   2955 
   2956 void
   2957 _print_capture_ts(int unit, bcm_port_t port)
   2958 {
   2959     int rv;
   2960     uint64 time;
   2961 
   2962     rv = bcm_port_control_phy_timesync_get(unit, port,
   2963                                            bcmPortControlPhyTimesyncCaptureTimestamp,
   2964                                            &time);
   2965 
   2966     if (rv != BCM_E_NONE) {
   2967         cli_out("bcm_port_control_phy_timesync_get "
   2968                 "failed with error  u=%d p=%d %s\n",
   2969                 unit, port, bcm_errmsg(rv));
   2970     }
   2971 
   2972     cli_out("Capture   TS = %08x%08x\n",
   2973             COMPILER_64_HI(time), COMPILER_64_LO(time));
   2974 }
   2975 
   2976 
   2977 
   2978 
   2979 
   2980 
   2981 #if defined(PHYMOD_SUPPORT)
   2982 
   2983 int
   2984 phymod_sym_access(int u, args_t *a, int intermediate, soc_pbmp_t *pbm)
   2985 {
   2986     phymod_symbols_iter_t iter; 
   2987     phymod_symbols_t *symbols;
   2988     phymod_phy_access_t pm_acc;
   2989     int rv, p, dport;
   2990     char hdr[32];
   2991 
   2992     rv = phymod_symop_init(&iter, a);
   2993     if (rv != CMD_OK) {
   2994         return rv;
   2995     }
   2996 
   2997     /* coverity[overrun-local] */
   2998     DPORT_SOC_PBMP_ITER(u, *pbm, dport, p) {
   2999         if (phymod_sym_info(u, p, intermediate, &iter, &pm_acc) < 0) {
   3000             continue;
   3001         }
   3002         /* coverity[overrun-local] */
   3003         if (IS_CPRI_PORT(u, p)) {
   3004             pm_acc.type = phymodDispatchTypeTscf_gen3;
   3005         }
   3006         if (phymod_diag_symbols_table_get(&pm_acc, &symbols) < 0) {
   3007             continue;
   3008         }
   3009         /* coverity[illegal_address] */
   3010         rv = sal_snprintf(hdr, sizeof(hdr), "Port %s%s:\n",
   3011                           SOC_PORT_NAME(u, p),
   3012                           intermediate ? " (int)" : "");
   3013         if (rv >= sizeof(hdr)) {
   3014             continue;
   3015         }
   3016         rv = phymod_symop_exec(&iter, symbols, &pm_acc, hdr);
   3017         if (rv != CMD_OK) {
   3018             return rv;
   3019         }
   3020     }
   3021 
   3022     return phymod_symop_cleanup(&iter);
   3023 }
   3024 
   3025 #endif /* defined(PHYMOD_SUPPORT) */
   3026 
   3027 /* #define INCLUDE_TIMESYNC_DVT_TESTS */
   3028 #ifdef  INCLUDE_TIMESYNC_DVT_TESTS
   3029 cmd_result_t phy_test1588(int unit, args_t *args, soc_pbmp_t *pbm);
   3030 #endif
   3031 
   3032 STATIC cmd_result_t
   3033 _if_esw_phy_info(int u, args_t *a)
   3034 {
   3035     soc_pbmp_t pbm;
   3036     soc_port_t p, p1, dport;
   3037     char remark[40];
   3038 #if defined(BCM_KATANA2_SUPPORT)
   3039     soc_field_t wc_xfi_mode_sel_fld[] =
   3040         { WC0_8_XFI_MODE_SELf, WC1_8_XFI_MODE_SELf };
   3041     uint32 wc_xfi_mode_sel_val[2] = { 0 };
   3042     uint32 top_misc_control_1_val = 0;
   3043 #endif
   3044 
   3045     remark[0] = '\0';
   3046 #if defined(BCM_KATANA2_SUPPORT)
   3047     if (SOC_IS_KATANA2(u) && !SOC_IS_SABER2(u)) {
   3048         SOC_IF_ERROR_RETURN(READ_TOP_MISC_CONTROL_1r
   3049                             (u, &top_misc_control_1_val));
   3050         wc_xfi_mode_sel_val[0] =
   3051             soc_reg_field_get(u, TOP_MISC_CONTROL_1r,
   3052                               top_misc_control_1_val,
   3053                               wc_xfi_mode_sel_fld[0]);
   3054         wc_xfi_mode_sel_val[1] =
   3055             soc_reg_field_get(u, TOP_MISC_CONTROL_1r,
   3056                               top_misc_control_1_val,
   3057                               wc_xfi_mode_sel_fld[1]);
   3058     }
   3059 #endif
   3060     SOC_PBMP_ASSIGN(pbm, PBMP_PORT_ALL(u));
   3061     SOC_PBMP_REMOVE(pbm, PBMP_HG_SUBPORT_ALL(u));
   3062     SOC_PBMP_REMOVE(pbm, PBMP_REQ_ALL(u));
   3063     cli_out("Phy mapping dump:\n");
   3064     cli_out("%10s %5s %5s %5s %5s %23s %17s\n",
   3065             "port", "id0", "id1", "addr", "iaddr", "name", "timeout");
   3066     /* Coverity
   3067      * DPORT_SOC_PBMP_ITER checks that dport is valid.
   3068      */
   3069     /* coverity[overrun-local] */
   3070     DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   3071         if (phy_port_info[u] == NULL) {
   3072             continue;
   3073         }
   3074         p1 = p;
   3075 #if defined(BCM_KATANA2_SUPPORT)
   3076         if (SOC_IS_KATANA2(u) && !SOC_IS_SABER2(u)) {
   3077             switch (p) {
   3078                 case 25:
   3079                 case 36:
   3080                     if (wc_xfi_mode_sel_val[0]) {
   3081                         p1 = (p == 25) ? 32 : 34;
   3082                         sal_sprintf(remark, "XFI#Int:%d:==>Ext:%d:", p, p1);
   3083                     }
   3084                     break;
   3085                 case 26:
   3086                 case 39:
   3087                     if (wc_xfi_mode_sel_val[1]) {
   3088                         p1 = (p == 26) ? 29 : 31;
   3089                         sal_sprintf(remark, "XFI#Int:%d:==>Ext:%d:", p, p1);
   3090                     }
   3091                     break;
   3092                 default:
   3093                     remark[0] = '\0';
   3094                     break;
   3095             }
   3096         }
   3097 #endif
   3098 
   3099 #ifdef PORTMOD_SUPPORT
   3100         if(soc_feature(u, soc_feature_portmod)) {
   3101             phymod_core_access_t core_acc, internal_core;
   3102             phymod_core_info_t   core_info;
   3103             int nof_cores = 0 , an_timeout = -1;
   3104             int phy = 0, core_num = 0, is_legacy =0;
   3105             int range_start = 0;
   3106             int is_first_range;
   3107             portmod_port_diag_info_t diag_info;
   3108             int diag_rv;
   3109             uint8   pcount=0;
   3110             char    lnstr[32], *pname, namelen; 
   3111             pm_info_t pm_info;
   3112             int mod = 4;
   3113 
   3114             phymod_core_access_t_init(&core_acc);
   3115             phymod_core_access_t_init(&internal_core);
   3116             phymod_core_info_t_init(&core_info);
   3117             sal_memset(&diag_info, 0, sizeof(portmod_port_diag_info_t));
   3118 
   3119             portmod_port_main_core_access_get(u, p, -1, &core_acc, &nof_cores);
   3120             if(nof_cores == 0) {
   3121                 continue;
   3122             }
   3123             /* check if the external phy is a legacy phy */
   3124             diag_rv = portmod_port_check_legacy_phy(u, p, &is_legacy);
   3125             if (diag_rv) {
   3126                 continue;
   3127             }
   3128 
   3129             portmod_port_main_core_access_get(u, p, 0, &internal_core, &nof_cores);
   3130             if(nof_cores == 0) {
   3131                 continue;
   3132             }
   3133 
   3134             diag_rv = portmod_port_diag_info_get(u, p, &diag_info);
   3135             if(diag_rv){ 
   3136                 continue;
   3137             }
   3138 
   3139             diag_rv = portmod_port_core_num_get(u, p, &core_num);
   3140             if (diag_rv){ 
   3141                 continue;
   3142             }
   3143 
   3144             diag_rv = portmod_pm_info_get(u, p, &pm_info);
   3145             if (diag_rv) {
   3146                 continue;
   3147             }
   3148 
   3149 #ifdef PORTMOD_PM8X50_SUPPORT
   3150             if (pm_info->type == portmodDispatchTypePm8x50) {
   3151                mod = 8;
   3152             }
   3153 #endif
   3154             is_first_range = TRUE;
   3155             PORTMOD_PBMP_ITER(diag_info.phys, phy){
   3156                 if( is_first_range ){
   3157                     range_start = phy ;
   3158                     is_first_range = FALSE;
   3159                 }
   3160             }
   3161 
   3162             if (IS_QSGMII_PORT(u, p)) {
   3163                 range_start = (range_start - 1)/4 + 1;
   3164             }
   3165 
   3166             an_timeout = soc_property_port_get(u, p,
   3167                               spn_PHY_AUTONEG_TIMEOUT, 250000);
   3168 #ifdef PORTMOD_CPM4X25_SUPPORT
   3169             if (pm_info->type == portmodDispatchTypeCpm4x25) {
   3170                 pname = "CPRIFA0";
   3171                 if (IS_E_PORT(u, p)) {
   3172                     SOC_IF_ERROR_RETURN
   3173                         (phymod_core_info_get(&core_acc, &core_info));
   3174                 }
   3175             } else
   3176 #endif
   3177             {
   3178                 if ( !is_legacy ) {
   3179                     SOC_IF_ERROR_RETURN
   3180                         (phymod_core_info_get(&core_acc, &core_info));
   3181                 }
   3182              
   3183                 PORTMOD_PBMP_COUNT(diag_info.phys, pcount);
   3184 
   3185                 pname = phymod_core_version_t_mapping[core_info.core_version].key;
   3186             }
   3187             namelen = strlen(pname);
   3188 
   3189             sal_snprintf(lnstr, sizeof(lnstr), "%s", pname); 
   3190             sal_snprintf(lnstr+namelen-2, sizeof(lnstr)-(namelen-2), "-%s/%02d/", pname+namelen-2, core_num); 
   3191 
   3192             pname = lnstr;
   3193             while (*pname != '-') {
   3194                 *pname = sal_toupper(*pname); 
   3195                  pname++;
   3196             }
   3197 
   3198             pname = lnstr+strlen(lnstr); 
   3199             if (pcount == 8) {
   3200                sal_snprintf(pname,sizeof(lnstr), "%d", pcount);
   3201             } else if (pcount == 4) {
   3202                if (mod == 8) {
   3203                    sal_snprintf(pname,sizeof(lnstr), "%d-%d", (range_start-1)%mod, ((range_start-1)%mod)+3);
   3204                } else {
   3205                    sal_snprintf(pname,sizeof(lnstr), "%d", pcount);
   3206                }
   3207             } else if (pcount == 2) {
   3208                sal_snprintf(pname,sizeof(lnstr), "%d-%d", (range_start-1)%mod, ((range_start-1)%mod)+1);
   3209             } else {
   3210                sal_snprintf(pname,sizeof(lnstr), "%d", (range_start-1)%mod);
   3211             }
   3212 
   3213             if ( !is_legacy ) {
   3214                 cli_out("%5s(%3d) %5x %5x %5x %5x %23s %10d %s \n",
   3215                         SOC_PORT_NAME(u, p), p1,
   3216                         core_info.phy_id0,
   3217                         core_info.phy_id1,
   3218                         core_acc.access.addr,
   3219                         internal_core.access.addr,
   3220                         lnstr, an_timeout,
   3221                         /*soc_phy_an_timeout_get(u, p), */
   3222                         remark);
   3223             } else {
   3224                 cli_out("%5s(%3d) %5x %5x %5x %5x %23s %10d %s \n",
   3225                         SOC_PORT_NAME(u, p), p1,
   3226                         soc_phy_id0reg_get(u, p),
   3227                         soc_phy_id1reg_get(u, p),
   3228                         soc_phy_addr_of_port(u, p),
   3229                         internal_core.access.addr,
   3230                         soc_phy_name_get(u, p),
   3231                         soc_phy_an_timeout_get(u, p), remark);
   3232             }
   3233        } else 
   3234 #endif
   3235        {
   3236         cli_out("%5s(%3d) %5x %5x %5x %5x %23s %10d %s \n",
   3237                 SOC_PORT_NAME(u, p), p1,
   3238                 soc_phy_id0reg_get(u, p),
   3239                 soc_phy_id1reg_get(u, p),
   3240                 soc_phy_addr_of_port(u, p),
   3241                 soc_phy_addr_int_of_port(u, p),
   3242                 soc_phy_name_get(u, p),
   3243                 soc_phy_an_timeout_get(u, p), remark);
   3244        }
   3245     }
   3246 
   3247     return CMD_OK;
   3248 }
   3249 
   3250 #if defined(PHYMOD_SUPPORT)
   3251 STATIC cmd_result_t
   3252 _if_esw_phy_phymod(int u, args_t *a)
   3253 {
   3254     soc_pbmp_t pbm;
   3255     soc_port_t p, dport;
   3256     char *c;
   3257     int rv = 0;
   3258 
   3259     if ((c = ARG_GET(a)) != NULL) {
   3260         soc_phymod_ctrl_t *pmc;
   3261         soc_phymod_phy_t *phy;
   3262         phy_ctrl_t *pc;
   3263         int phy_id = sal_ctoi(c, NULL);
   3264 #ifdef PORTMOD_SUPPORT
   3265         if( sal_strcasecmp(c, "addr") == 0 ) {
   3266             if (soc_feature(u, soc_feature_portmod)) {
   3267                 if ((c = ARG_GET(a)) != NULL) {
   3268                     phymod_dbg_addr = sal_ctoi(c, NULL);
   3269                     if ((c = ARG_GET(a)) != NULL) {
   3270                         phymod_dbg_mask = sal_ctoi(c, NULL);
   3271                         if ((c = ARG_GET(a)) != NULL) {
   3272                             phymod_dbg_lane = sal_ctoi(c, NULL);
   3273                         } else {
   3274                             phymod_dbg_lane = 0;
   3275                         }
   3276                     }
   3277                 }
   3278                 cli_out("addr=0x%0x mask=0x%08x lane=%0x", 
   3279                         phymod_dbg_addr, phymod_dbg_mask, phymod_dbg_lane) ;
   3280                 cli_out("\n");
   3281             }
   3282             return CMD_OK;
   3283         }
   3284 #endif
   3285         if (parse_bcm_pbmp(u, c, &pbm) == 0) {
   3286             DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   3287                 if (phy_port_info[u] == NULL) {
   3288                     continue;
   3289                 }
   3290 #ifdef PORTMOD_SUPPORT
   3291                 if (soc_feature(u, soc_feature_portmod)) {
   3292                     if ((c = ARG_GET(a)) != NULL) {
   3293                         uint16 phyad = 0;
   3294                         phyad = portmod_port_to_phyaddr(u, p);
   3295                         phymod_dbg_addr = phyad;
   3296                         phymod_dbg_mask = sal_ctoi(c, NULL);
   3297                         if ((c = ARG_GET(a)) != NULL) {
   3298                             phymod_dbg_lane = sal_ctoi(c, NULL);
   3299                         } else {
   3300                             phymod_dbg_lane = 0;
   3301                         }
   3302                     }
   3303                     cli_out("%5s(%3d) %d  ",
   3304                             SOC_PORT_NAME(u, p), p,
   3305                             SOC_PORT_BINDEX(u, p));
   3306                     cli_out("addr=0x%0x mask=0x%08x lane=0x%0x", 
   3307                             phymod_dbg_addr, phymod_dbg_mask, phymod_dbg_lane) ;
   3308                 } else 
   3309 #endif
   3310                 {
   3311                 pc = INT_PHY_SW_STATE(u, p);
   3312                 if (pc == NULL) {
   3313                     continue;
   3314                 }
   3315                 if ((c = ARG_GET(a)) != NULL) {
   3316                     uint16 phyad = 0;
   3317                     soc_phy_cfg_addr_get(u, p, SOC_PHY_INTERNAL, &phyad);
   3318                     phymod_dbg_addr = phyad;
   3319                     phymod_dbg_mask = sal_ctoi(c, NULL);
   3320                     if ((c = ARG_GET(a)) != NULL) {
   3321                         phymod_dbg_lane = sal_ctoi(c, NULL);
   3322                     } else {
   3323                         phymod_dbg_lane = 0;
   3324                     }
   3325                     continue;
   3326                 }
   3327                 pmc = &pc->phymod_ctrl;
   3328                 cli_out("%5s(%3d) %d  ",
   3329                         SOC_PORT_NAME(u, p), p,
   3330                         SOC_PORT_BINDEX(u, p));
   3331                 phy = pmc->phy[0];
   3332                 if (phy) {
   3333                     cli_out("phy(0x%08x)->core(0x%08x)  ",
   3334                             phy->obj.obj_id,
   3335                             phy->core->obj.obj_id);
   3336                 }
   3337                 }
   3338                 cli_out("\n");
   3339             }
   3340         } else {
   3341             rv = soc_phymod_phy_create(u, -1, &phy);
   3342             if (SOC_SUCCESS(rv)) {
   3343                 cli_out("phymod ID %d created\n", phy->obj.obj_id);
   3344             }
   3345             rv = soc_phymod_phy_find_by_id(u, phy_id, &phy);
   3346             cli_out("phymod ID %d%s found\n", phy_id, (rv < 0) ? " not" : "");
   3347         }
   3348     }
   3349     return CMD_OK;
   3350 }
   3351 #endif /* defined(PHYMOD_SUPPORT) */
   3352 
   3353 STATIC cmd_result_t
   3354 _if_esw_phy_eee(int u, args_t *a)
   3355 {
   3356     soc_pbmp_t pbm;
   3357     soc_port_t p, dport;
   3358     char *c;
   3359     int rv = 0;
   3360     char *str, *latency_str;
   3361     uint32 eee_mode_value, eee_auto_mode_value;
   3362     uint32 latency, idle = 0, tx_events, tx_duration, rx_events, rx_duration;
   3363     uint32 flags;
   3364     int i;
   3365     parse_table_t pt;
   3366     char *mode_type = NULL, *lstr = NULL, *stats = NULL;
   3367     int idle_th = -1;
   3368 
   3369     if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) {
   3370         cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c);
   3371         return CMD_FAIL;
   3372     }
   3373 
   3374     if ((c = ARG_CUR(a)) != NULL) {
   3375 
   3376         parse_table_init(u, &pt);
   3377         parse_table_add(&pt, "MOde", PQ_DFL | PQ_STRING, 0, &mode_type, 0);
   3378 
   3379         parse_table_add(&pt, "LAtency", PQ_DFL | PQ_STRING, 0, &lstr, 0);
   3380 
   3381         parse_table_add(&pt, "IDle_th", PQ_DFL | PQ_INT, 0, &idle_th, 0);
   3382 
   3383         parse_table_add(&pt, "STats", PQ_DFL | PQ_STRING, 0, &stats, 0);
   3384 
   3385         if (parse_arg_eq(a, &pt) < 0) {
   3386             parse_arg_eq_done(&pt);
   3387             return CMD_USAGE;
   3388         }
   3389         if (ARG_CNT(a) > 0) {
   3390             cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a));
   3391             parse_arg_eq_done(&pt);
   3392             return CMD_USAGE;
   3393         }
   3394 
   3395         flags = 0;
   3396 
   3397         for (i = 0; i < pt.pt_cnt; i++) {
   3398             if (pt.pt_entries[i].pq_type & PQ_PARSED) {
   3399                 flags |= (1 << i);
   3400             }
   3401         }
   3402 
   3403         DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   3404 
   3405             if (flags & 0x1) {
   3406 
   3407                 if (sal_strcasecmp(mode_type, "native") == 0) {
   3408                     rv = bcm_port_phy_control_set(u, p,
   3409                                                   BCM_PORT_PHY_CONTROL_EEE,
   3410                                                   1);
   3411                 }
   3412                 if (sal_strcasecmp(mode_type, "auto") == 0) {
   3413                     rv = bcm_port_phy_control_set(u, p,
   3414                                                   BCM_PORT_PHY_CONTROL_EEE_AUTO,
   3415                                                   1);
   3416                 }
   3417                 if (sal_strcasecmp(mode_type, "none") == 0) {
   3418                     rv = bcm_port_phy_control_set(u, p,
   3419                                                   BCM_PORT_PHY_CONTROL_EEE_AUTO,
   3420                                                   0);
   3421                     rv = bcm_port_phy_control_set(u, p,
   3422                                                   BCM_PORT_PHY_CONTROL_EEE,
   3423                                                   0);
   3424                 }
   3425 
   3426                 if (rv == BCM_E_NONE) {
   3427                     cli_out("Port %s EEE mode set to %s EEE mode\n",
   3428                             SOC_PORT_NAME(u, p), mode_type);
   3429                 } else {
   3430                     if (rv == BCM_E_UNAVAIL) {
   3431                         cli_out("Port %s EEE %s mode not available\n",
   3432                                 SOC_PORT_NAME(u, p), mode_type);
   3433                     } else {
   3434                         cli_out("Port %s EEE %s mode set unsuccessful\n",
   3435                                 SOC_PORT_NAME(u, p), mode_type);
   3436                     }
   3437                 }
   3438                 rv = bcm_port_phy_control_get(u, p,
   3439                                               BCM_PORT_PHY_CONTROL_EEE_AUTO,
   3440                                               &eee_auto_mode_value);
   3441                 if ((rv == BCM_E_NONE) && (eee_auto_mode_value == 1)) {
   3442                     str = "auto";
   3443                 } else {
   3444                     rv = bcm_port_phy_control_get(u, p,
   3445                                                   BCM_PORT_PHY_CONTROL_EEE,
   3446                                                   &eee_mode_value);
   3447                     if (rv == BCM_E_NONE) {
   3448                         if (eee_mode_value == 0 && eee_auto_mode_value == 0) {
   3449                             str = "none";
   3450                         } else {
   3451                             str = "native";
   3452                         }
   3453                     } else {
   3454                         str = "NA";
   3455                     }
   3456                 }
   3457                 cli_out("Port %s EEE mode = %s\n", SOC_PORT_NAME(u, p), str);
   3458             }
   3459 
   3460             if (flags & 0x2) {
   3461                 if (sal_strcasecmp(lstr, "fixed") == 0) {
   3462                     rv = bcm_port_phy_control_set(u, p,
   3463                                                   BCM_PORT_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY,
   3464                                                   1);
   3465     		if (rv != BCM_E_NONE) {
   3466     			return CMD_FAIL;
   3467     		}
   3468     	    }
   3469     	    if (sal_strcasecmp(lstr, "variable") == 0) {
   3470     		    rv = bcm_port_phy_control_set(u, p,
   3471     				    BCM_PORT_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY,
   3472     				    0);
   3473                 	if (rv != BCM_E_NONE) {
   3474     			return CMD_FAIL;
   3475     		}
   3476                 }
   3477                 rv = bcm_port_phy_control_get(u, p,
   3478                                               BCM_PORT_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY,
   3479                                               &latency);
   3480                 if (rv == BCM_E_NONE) {
   3481                     if (latency == 1) {     /* AutogrEEEn Ctrl Reg. */
   3482                         str = "fixed";      /*  bit_2 == 0  */
   3483                     } else {
   3484                         str = "variable";   /*  bit_2 == 1  */
   3485                     }
   3486                     cli_out("Port %s EEE Auto mode Latency = %s\n",
   3487                             SOC_PORT_NAME(u, p), str);
   3488                 }
   3489             }
   3490 
   3491             if (flags & 0x4) {
   3492                 if ((rv =
   3493                      bcm_port_phy_control_set(u, p,
   3494                                               BCM_PORT_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD,
   3495                                               idle_th)) != BCM_E_NONE) {
   3496                     return CMD_FAIL;
   3497                 }
   3498                 if ((rv = bcm_port_phy_control_get(u, p,
   3499                                                    BCM_PORT_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD,
   3500                                                    &idle)) != BCM_E_NONE) {
   3501                     return CMD_FAIL;
   3502                 }
   3503                 cli_out("Port %s EEE Auto mode IDLE Threshold = %d\n",
   3504                         SOC_PORT_NAME(u, p), idle);
   3505             }
   3506 
   3507             if (flags & 0x8) {
   3508                 if (sal_strcasecmp(stats, "get") == 0) {
   3509                     (void)bcm_port_phy_control_get(u, p,
   3510                                                    BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_EVENTS,
   3511                                                    &tx_events);
   3512                     (void)bcm_port_phy_control_get(u, p,
   3513                                                    BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_DURATION,
   3514                                                    &tx_duration);
   3515                     (void)bcm_port_phy_control_get(u, p,
   3516                                                    BCM_PORT_PHY_CONTROL_EEE_RECEIVE_EVENTS,
   3517                                                    &rx_events);
   3518                     (void)bcm_port_phy_control_get(u, p,
   3519                                                    BCM_PORT_PHY_CONTROL_EEE_RECEIVE_DURATION,
   3520                                                    &rx_duration);
   3521                     cli_out("Port %s Tx events = %u TX Duration = %u  "
   3522                             "RX events = %u RX Duration = %u\n",
   3523                             SOC_PORT_NAME(u, p), tx_events,
   3524                             tx_duration, rx_events, rx_duration);
   3525                 }
   3526                 if (sal_strcasecmp(stats, "clear") == 0) {
   3527                     (void)bcm_port_phy_control_set(u, p,
   3528                                                    BCM_PORT_PHY_CONTROL_EEE_STATISTICS_CLEAR,
   3529                                                    1);
   3530                     cli_out("Port %s Statistics Cleared \n",
   3531                             SOC_PORT_NAME(u, p));
   3532                 }
   3533 
   3534                 if (sal_strcasecmp(stats, "all") == 0) {
   3535                     (void)bcm_port_phy_control_get(u, p,
   3536                                                    BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_EVENTS,
   3537                                                    &tx_events);
   3538                     (void)bcm_port_phy_control_get(u, p,
   3539                                                    BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_DURATION,
   3540                                                    &tx_duration);
   3541                     (void)bcm_port_phy_control_get(u, p,
   3542                                                    BCM_PORT_PHY_CONTROL_EEE_RECEIVE_EVENTS,
   3543                                                    &rx_events);
   3544                     rv = bcm_port_phy_control_get(u, p,
   3545                                                   BCM_PORT_PHY_CONTROL_EEE_RECEIVE_DURATION,
   3546                                                   &rx_duration);
   3547                     if (rv == BCM_E_NONE) {
   3548                         cli_out("Port %s EEE Statistics\n",
   3549                                 SOC_PORT_NAME(u, p));
   3550                         cli_out("\tEEE Transmit Events\t%u\n"  , tx_events);
   3551                         cli_out("\tEEE Transmit Duration\t%u\n", tx_duration);
   3552                         cli_out("\tEEE Receive  Events\t%u\n"  , rx_events);
   3553                         cli_out("\tEEE Receive  Duration\t%u\n", rx_duration);
   3554                     }
   3555                 }
   3556             }
   3557         }
   3558         /* free allocated memory from arg parsing */
   3559         parse_arg_eq_done(&pt);
   3560     } else {
   3561 
   3562         cli_out("EEE Details:\n");
   3563         cli_out("%10s %16s %16s %14s %14s\n",
   3564                 "port", "name", "eee mode", "latency mode",
   3565                 "Idle Threshold(ms)");
   3566         /* coverity[overrun-local] */
   3567         DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   3568             latency_str = "NA";
   3569             idle = 0;
   3570 
   3571             if ((rv =
   3572                  bcm_port_phy_control_get(u, p,
   3573                                           BCM_PORT_PHY_CONTROL_EEE_AUTO,
   3574                                           &eee_auto_mode_value)) ==
   3575                 BCM_E_FAIL) {
   3576                 cli_out("Phy control get: "
   3577                         "BCM_PORT_PHY_CONTROL_EEE_AUTO failed\n");
   3578                 return BCM_E_FAIL;
   3579             }
   3580             if ((rv == BCM_E_NONE) && (eee_auto_mode_value == 1)) {
   3581                 str = "auto";
   3582                 rv = bcm_port_phy_control_get(u, p,
   3583                                               BCM_PORT_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY,
   3584                                               &latency);
   3585                 if (rv == BCM_E_NONE) {
   3586                     if (latency == 1) {     /* AutogrEEEn Ctrl Reg. */
   3587                         latency_str = "fixed";      /*  bit_2 == 0  */
   3588                     } else {
   3589                         latency_str = "variable";   /*  bit_2 == 1  */
   3590                     }
   3591                 } else {
   3592                     latency_str = "NA";
   3593                 }
   3594                 rv = bcm_port_phy_control_get(u, p,
   3595                                               BCM_PORT_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD,
   3596                                               &idle);
   3597                 if (rv != BCM_E_NONE) {
   3598                     idle = 0;
   3599                 }
   3600             } else {
   3601                 if ((rv =
   3602                      bcm_port_phy_control_get(u, p,
   3603                                               BCM_PORT_PHY_CONTROL_EEE,
   3604                                               &eee_mode_value)) ==
   3605                     BCM_E_FAIL) {
   3606                     cli_out("Phy control get: "
   3607                             "BCM_PORT_PHY_CONTROL_EEE failed\n");
   3608                     return BCM_E_FAIL;
   3609                 }
   3610                 if (eee_mode_value == 1) {
   3611                     str = "native";
   3612                 } else {
   3613                     str = "none";
   3614                 }
   3615             }
   3616             /* coverity[illegal_address] */
   3617             cli_out("%5s(%3d) %16s %14s %14s %10d\n",
   3618                     SOC_PORT_NAME(u, p), p,
   3619                     soc_phy_name_get(u, p), str, latency_str, idle);
   3620         }
   3621     }
   3622     return CMD_OK;
   3623 }
   3624 
   3625 STATIC cmd_result_t
   3626 _if_esw_phy_timesync(int u, args_t *a)
   3627 {
   3628     soc_pbmp_t pbm;
   3629     soc_port_t p, dport;
   3630     char *c;
   3631     int i, rv = 0;
   3632     bcm_port_phy_timesync_config_t conf;
   3633     uint64 val64;
   3634 
   3635     sal_memset(&conf, 0, sizeof(conf));
   3636 
   3637     if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) {
   3638         cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c);
   3639         return CMD_FAIL;
   3640     }
   3641     if ((c = ARG_CUR(a)) != NULL) {
   3642         parse_table_t pt;
   3643         uint32 enable, capture_ts, heartbeat_ts, rx_crc, as, l2, ip4, ip6, ec,      /* bool */
   3644             itpid, otpid, tx_offset, rx_offset, original_timecode_seconds,
   3645             original_timecode_nanoseconds, load_all, frame_sync, flags,
   3646             flags_2, ibts_sync = 0;
   3647         uint32 ibts_dreq = 0, ibts_pdreq = 0, ibts_pdrsp = 0,
   3648                ibts_resv_id_chk = 0, ibts_resv_id_upd = 0, ibts_resv_id = 0,
   3649                ibts_upd_fu = 0, ibts_upd_drsp = 0, ibts_longts = 0;
   3650         char *gmode_str = NULL, *tx_sync_mode_str = NULL,
   3651              *tx_delay_request_mode_str = NULL,
   3652              *tx_pdelay_request_mode_str = NULL,
   3653              *tx_pdelay_response_mode_str = NULL, *rx_sync_mode_str = NULL,
   3654              *rx_delay_request_mode_str = NULL,
   3655              *rx_pdelay_request_mode_str = NULL,
   3656              *rx_pdelay_response_mode_str = NULL, *framesync_mode_str = NULL,
   3657              *syncout_mode_str = NULL, *ibts_match = NULL;
   3658 
   3659         parse_table_init(u, &pt);
   3660         parse_table_add(&pt, "ENable", 
   3661                         PQ_BOOL | PQ_DFL | 
   3662                         PQ_NO_EQ_OPT, 0,
   3663                         &enable, 0);                      /* index 0 */
   3664         parse_table_add(&pt, "CaptureTS",
   3665                         PQ_BOOL | PQ_DFL | 
   3666                         PQ_NO_EQ_OPT, 0, 
   3667                         &capture_ts, 0);                  /* index 1 */
   3668         parse_table_add(&pt, "HeartbeatTS",
   3669                         PQ_BOOL | PQ_DFL |
   3670                         PQ_NO_EQ_OPT, 0, 
   3671                         &heartbeat_ts, 0);                /* index 2 */
   3672         parse_table_add(&pt, "RxCrc",
   3673                         PQ_BOOL | PQ_DFL |
   3674                         PQ_NO_EQ_OPT, 0,
   3675                         &rx_crc, 0);                      /* index 3 */
   3676         parse_table_add(&pt, "AS", 
   3677                         PQ_BOOL | PQ_DFL |
   3678                         PQ_NO_EQ_OPT, 0,
   3679                         &as, 0);                          /* index 4 */
   3680         parse_table_add(&pt, "L2",
   3681                         PQ_BOOL | PQ_DFL |
   3682                         PQ_NO_EQ_OPT, 0,
   3683                         &l2, 0);                          /* index 5 */
   3684         parse_table_add(&pt, "IP4", 
   3685                         PQ_BOOL | PQ_DFL | 
   3686                         PQ_NO_EQ_OPT, 0,
   3687                         &ip4, 0);                         /* index 6 */
   3688         parse_table_add(&pt, "IP6",
   3689                         PQ_BOOL | PQ_DFL |
   3690                         PQ_NO_EQ_OPT, 0, 
   3691                         &ip6, 0);                         /* index 7 */
   3692         parse_table_add(&pt, "ExtClock",
   3693                         PQ_BOOL | PQ_DFL |
   3694                         PQ_NO_EQ_OPT, 0,
   3695                         &ec, 0);                         /* index 8 */
   3696         parse_table_add(&pt, "ITpid",
   3697                         PQ_DFL | PQ_INT, 0,
   3698                         &itpid, 0);                      /* index 9 */
   3699         parse_table_add(&pt, "OTpid",
   3700                         PQ_DFL | PQ_INT,      
   3701                         0, &otpid, 0);                   /* index 10 */
   3702         parse_table_add(&pt, "GMode",
   3703                         PQ_DFL | PQ_STRING,   
   3704                         0, &gmode_str, 0);               /* index 11 */
   3705         parse_table_add(&pt, "TxOffset",
   3706                         PQ_DFL | PQ_INT,   
   3707                         0, &tx_offset, 0);               /* index 12 */
   3708         parse_table_add(&pt, "RxOffset",
   3709                         PQ_DFL | PQ_INT,   
   3710                         0, &rx_offset, 0);               /* index 13 */
   3711         parse_table_add(&pt, "TxSync",
   3712                         PQ_DFL | PQ_STRING,  
   3713                         0, &tx_sync_mode_str, 0);       /* index 14 */
   3714         parse_table_add(&pt, "TxDelayReq",
   3715                         PQ_DFL | PQ_STRING,      
   3716                         0, &tx_delay_request_mode_str,
   3717                         0);                            /* index 15 */
   3718         parse_table_add(&pt, "TxPdelayReq",
   3719                         PQ_DFL | PQ_STRING,     
   3720                         0, &tx_pdelay_request_mode_str,
   3721                         0); /* index 16 */
   3722         parse_table_add(&pt, "TxPdelayreS",
   3723                         PQ_DFL | PQ_STRING,     
   3724                         0, &tx_pdelay_response_mode_str,
   3725                         0);                               /* index 17 */
   3726         parse_table_add(&pt, "RxSync",
   3727                         PQ_DFL | PQ_STRING,  
   3728                         0, &rx_sync_mode_str, 0);        /* index 18 */
   3729         parse_table_add(&pt, "RxDelayReq",
   3730                         PQ_DFL | PQ_STRING,      
   3731                         0, &rx_delay_request_mode_str,
   3732                         0);                               /* index 19 */
   3733         parse_table_add(&pt, "RxPdelayReq",
   3734                         PQ_DFL | PQ_STRING,     
   3735                         0, &rx_pdelay_request_mode_str,
   3736                         0);                              /* index 20 */
   3737         parse_table_add(&pt, "RxPdelayreS",
   3738                         PQ_DFL | PQ_STRING,     
   3739                         0, &rx_pdelay_response_mode_str,
   3740                         0);                              /* index 21 */
   3741         parse_table_add(&pt, "OriginalTimecodeSeconds",
   3742                         PQ_DFL | PQ_INT,    
   3743                         0, &original_timecode_seconds,
   3744                         0);                              /* index 22 */
   3745         parse_table_add(&pt, "OriginalTimecodeNanoseconds",
   3746                         PQ_DFL | PQ_INT,        
   3747                         0, &original_timecode_nanoseconds,
   3748                         0);                              /* index 23 */
   3749         parse_table_add(&pt, "FramesyncMode",
   3750                         PQ_DFL | PQ_STRING,   
   3751                         0, &framesync_mode_str, 0);     /* index 24 */  
   3752         parse_table_add(&pt, "SyncoutMode",
   3753                         PQ_DFL | PQ_STRING,     
   3754                         0, &syncout_mode_str, 0);       /* index 25 */
   3755         parse_table_add(&pt, "LoadAll",
   3756                         PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,    
   3757                         0, &load_all, 0);                /* index 26 */
   3758         parse_table_add(&pt, "FrameSync",
   3759                         PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,  
   3760                         0, &frame_sync, 0);             /* index 27 */
   3761         parse_table_add(&pt, "InBandSync",
   3762                         PQ_DFL | PQ_BOOL | PQ_NO_EQ_OPT,
   3763                         0, &ibts_sync, 0);              /* index 28 */
   3764         parse_table_add(&pt, "InBandDelayRequest",
   3765                         PQ_DFL | PQ_BOOL | PQ_NO_EQ_OPT,
   3766                         0, &ibts_dreq, 0);              /* index 29 */
   3767         parse_table_add(&pt, "InBandPdelayRequest",
   3768                         PQ_DFL | PQ_BOOL | PQ_NO_EQ_OPT,
   3769                         0, &ibts_pdreq, 0);               /* index 30 */
   3770         parse_table_add(&pt, "InBandPdelayreSponse",
   3771                         PQ_DFL | PQ_BOOL | PQ_NO_EQ_OPT,
   3772                         0, &ibts_pdrsp, 0);              /* index 31 */
   3773         parse_table_add(&pt, "InBandID",
   3774                         PQ_DFL | PQ_INT, 0, &ibts_resv_id,
   3775                         0);                           /* flag_2 index 0 */
   3776         parse_table_add(&pt, "InBandIDCheck",
   3777                         PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   3778                         0, &ibts_resv_id_chk, 0);   /* flag_2 index 1 */
   3779         parse_table_add(&pt, "InBandIDUpdate",
   3780                         PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   3781                         0, &ibts_resv_id_upd, 0);  /* flag_2 index 2 */
   3782         parse_table_add(&pt, "InBandMATch",
   3783                         PQ_DFL | PQ_STRING, "none",
   3784                         &ibts_match, 0);   /* flag_2 index 3 */
   3785         parse_table_add(&pt, "InBandFollowUpAssist",
   3786                         PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   3787                         0, &ibts_upd_fu, 0);
   3788         parse_table_add(&pt, "InBandDelayRespAssist",
   3789                         PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   3790                         0, &ibts_upd_drsp, 0);
   3791         parse_table_add(&pt, "InBandLongTimeStamp",
   3792                         PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   3793                         0, &ibts_longts, 0);
   3794 
   3795         if (parse_arg_eq(a, &pt) < 0) {
   3796             parse_arg_eq_done(&pt);
   3797             return CMD_USAGE;
   3798         }
   3799         if (ARG_CNT(a) > 0) {
   3800             cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a));
   3801             parse_arg_eq_done(&pt);
   3802             return CMD_USAGE;
   3803         }
   3804 
   3805         flags = 0;
   3806         flags_2 = 0;
   3807 
   3808         for (i = 0; i < pt.pt_cnt; i++) {
   3809             if (pt.pt_entries[i].pq_type & PQ_PARSED) {
   3810                 if (i >= (sizeof(flags) * 8)) {
   3811                     flags_2 |= (1 << (i - (sizeof(flags) * 8)));
   3812                 } else {
   3813                     flags   |= (1 << i);
   3814                 }
   3815 
   3816             }
   3817         }
   3818 
   3819         DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   3820             conf.validity_mask =
   3821                 0xffffffff & (~(BCM_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL));
   3822             if ((rv =
   3823                  bcm_port_phy_timesync_config_get(u, p,
   3824                                                   &conf)) == BCM_E_FAIL) {
   3825                 cli_out("bcm_port_phy_timesync_config_get() "
   3826                         "failed, u=%d, p=%d\n", u, p);
   3827                 parse_arg_eq_done(&pt);
   3828                 return BCM_E_FAIL;
   3829             }
   3830 
   3831             conf.validity_mask &=
   3832                 ~BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL;
   3833 
   3834             if (flags & (1U << 0)) {
   3835                 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_ENABLE;
   3836                 conf.flags |= enable ? BCM_PORT_PHY_TIMESYNC_ENABLE : 0;
   3837             }
   3838 
   3839             if (flags & (1U << 1)) {
   3840                 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE;
   3841                 conf.flags |=
   3842                     capture_ts ? BCM_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE :
   3843                     0;
   3844             }
   3845 
   3846             if (flags & (1U << 2)) {
   3847                 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE;
   3848                 conf.flags |=
   3849                     heartbeat_ts ? BCM_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE
   3850                     : 0;
   3851             }
   3852 
   3853             if (flags & (1U << 3)) {
   3854                 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_RX_CRC_ENABLE;
   3855                 conf.flags |=
   3856                     rx_crc ? BCM_PORT_PHY_TIMESYNC_RX_CRC_ENABLE : 0;
   3857             }
   3858 
   3859             if (flags & (1U << 4)) {
   3860                 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_8021AS_ENABLE;
   3861                 conf.flags |= as ? BCM_PORT_PHY_TIMESYNC_8021AS_ENABLE : 0;
   3862             }
   3863 
   3864             if (flags & (1U << 5)) {
   3865                 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_L2_ENABLE;
   3866                 conf.flags |= l2 ? BCM_PORT_PHY_TIMESYNC_L2_ENABLE : 0;
   3867             }
   3868 
   3869             if (flags & (1U << 6)) {
   3870                 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_IP4_ENABLE;
   3871                 conf.flags |= ip4 ? BCM_PORT_PHY_TIMESYNC_IP4_ENABLE : 0;
   3872             }
   3873 
   3874             if (flags & (1U << 7)) {
   3875                 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_IP6_ENABLE;
   3876                 conf.flags |= ip6 ? BCM_PORT_PHY_TIMESYNC_IP6_ENABLE : 0;
   3877             }
   3878 
   3879             if (flags & (1U << 8)) {
   3880                 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT;
   3881                 conf.flags |= ec ? BCM_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT : 0;
   3882             }
   3883 
   3884             if (flags & (1U << 9)) {
   3885                 conf.itpid = itpid;
   3886             }
   3887 
   3888             if (flags & (1U << 10)) {
   3889                 conf.otpid = otpid;
   3890             }
   3891 
   3892             if (flags & (1U << 11)) {
   3893                 conf.gmode =
   3894                     _convert_timesync_gmode_str(gmode_str, conf.gmode);
   3895             }
   3896 
   3897             if (flags & (1U << 12)) {
   3898                 conf.tx_timestamp_offset = tx_offset;
   3899             }
   3900 
   3901             if (flags & (1U << 13)) {
   3902                 conf.rx_timestamp_offset = rx_offset;
   3903             }
   3904 
   3905             if (flags & (1U << 14)) {
   3906                 conf.tx_sync_mode =
   3907                     _convert_timesync_egress_message_str(tx_sync_mode_str,
   3908                                                          conf.tx_sync_mode);
   3909             }
   3910 
   3911             if (flags & (1U << 15)) {
   3912                 conf.tx_delay_request_mode =
   3913                     _convert_timesync_egress_message_str
   3914                     (tx_delay_request_mode_str, conf.tx_delay_request_mode);
   3915             }
   3916 
   3917             if (flags & (1U << 16)) {
   3918                 conf.tx_pdelay_request_mode =
   3919                     _convert_timesync_egress_message_str
   3920                     (tx_pdelay_request_mode_str,
   3921                      conf.tx_pdelay_request_mode);
   3922             }
   3923 
   3924             if (flags & (1U << 17)) {
   3925                 conf.tx_pdelay_response_mode =
   3926                     _convert_timesync_egress_message_str
   3927                     (tx_pdelay_response_mode_str,
   3928                      conf.tx_pdelay_response_mode);
   3929             }
   3930 
   3931             if (flags & (1U << 18)) {
   3932                 conf.rx_sync_mode =
   3933                     _convert_timesync_ingress_message_str(rx_sync_mode_str,
   3934                                                           conf.
   3935                                                           rx_sync_mode);
   3936             }
   3937 
   3938             if (flags & (1U << 19)) {
   3939                 conf.rx_delay_request_mode =
   3940                     _convert_timesync_ingress_message_str
   3941                     (rx_delay_request_mode_str, conf.rx_delay_request_mode);
   3942             }
   3943 
   3944             if (flags & (1U << 20)) {
   3945                 conf.rx_pdelay_request_mode =
   3946                     _convert_timesync_ingress_message_str
   3947                     (rx_pdelay_request_mode_str,
   3948                      conf.rx_pdelay_request_mode);
   3949             }
   3950 
   3951             if (flags & (1U << 21)) {
   3952                 conf.rx_pdelay_response_mode =
   3953                     _convert_timesync_ingress_message_str
   3954                     (rx_pdelay_response_mode_str,
   3955                      conf.rx_pdelay_response_mode);
   3956             }
   3957 
   3958             if (flags & (1U << 22)) {
   3959 
   3960                 COMPILER_64_SET(conf.original_timecode.seconds, 0,
   3961                                 original_timecode_seconds);
   3962             }
   3963 
   3964             if (flags & (1U << 23)) {
   3965                 conf.original_timecode.nanoseconds =
   3966                     original_timecode_nanoseconds;
   3967             }
   3968 
   3969             if (flags & (1U << 24)) {
   3970                 conf.framesync.mode =
   3971                     _convert_framesync_mode_str(framesync_mode_str,
   3972                                                 conf.framesync.mode);
   3973             }
   3974 
   3975             if (flags & (1U << 25)) {
   3976                 conf.syncout.mode =
   3977                     _convert_syncout_mode_str(syncout_mode_str,
   3978                                               conf.syncout.mode);
   3979             }
   3980             if (flags & (1U << 28)) {
   3981                 conf.validity_mask |=
   3982                     BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL;
   3983                 conf.inband_control.flags &=
   3984                     ~BCM_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE;
   3985                 conf.inband_control.flags |=
   3986                     ibts_sync ? BCM_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE
   3987                     : 0;
   3988             }
   3989             if (flags & (1U << 29)) {
   3990                 conf.validity_mask |=
   3991                     BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL;
   3992                 conf.inband_control.flags &=
   3993                     ~BCM_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE;
   3994                 conf.inband_control.flags |=
   3995                     ibts_dreq ?
   3996                     BCM_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE : 0;
   3997             }
   3998             if (flags & (1U << 30)) {
   3999                 conf.validity_mask |=
   4000                     BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL;
   4001                 conf.inband_control.flags &=
   4002                     ~BCM_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE;
   4003                 conf.inband_control.flags |=
   4004                     ibts_pdreq ?
   4005                     BCM_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE : 0;
   4006             }
   4007             if (flags & (1U << 31)) {
   4008                 conf.validity_mask |=
   4009                     BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL;
   4010                 conf.inband_control.flags &=
   4011                     ~BCM_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE;
   4012                 conf.inband_control.flags |=
   4013                     ibts_pdrsp ?
   4014                     BCM_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE : 0;
   4015             }
   4016             if (flags_2 & (1U << 0)) {
   4017                 conf.validity_mask |=
   4018                     BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL;
   4019                 conf.inband_control.resv0_id = ibts_resv_id;
   4020             }
   4021             if (flags_2 & (1U << 1)) {
   4022                 conf.validity_mask |=
   4023                     BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL;
   4024                 conf.inband_control.flags &=
   4025                     ~BCM_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK;
   4026                 conf.inband_control.flags |=
   4027                     ibts_resv_id_chk ?
   4028                     BCM_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK : 0;
   4029             }
   4030             if (flags_2 & (1U << 2)) {
   4031                 conf.validity_mask |=
   4032                     BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL;
   4033                 conf.inband_control.flags &=
   4034                     ~BCM_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE;
   4035                 conf.inband_control.flags |=
   4036                     ibts_resv_id_upd ?
   4037                     BCM_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE : 0;
   4038             }
   4039             if (flags_2 & (1U << 3)) {
   4040                 conf.validity_mask |=
   4041                     BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL;
   4042                 _set_inband_timesync_matching_criterion(ibts_match,
   4043                                 &conf.inband_control.flags);
   4044             }
   4045             if (flags_2 & (1U << 4)) {
   4046                 conf.validity_mask |=
   4047                     BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL;
   4048                 conf.inband_control.flags &=
   4049                      (~BCM_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST);
   4050                 conf.inband_control.flags |= ( ibts_upd_fu ) ?
   4051                        BCM_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST : 0;
   4052             }
   4053             if (flags_2 & (1U << 5)) {
   4054                 conf.validity_mask |=
   4055                     BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL;
   4056                 conf.inband_control.flags &=
   4057                      (~BCM_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST);
   4058                 conf.inband_control.flags |= ( ibts_upd_drsp ) ?
   4059                        BCM_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST : 0;
   4060             }
   4061             if (flags_2 & (1U << 6)) {
   4062                 conf.validity_mask |=
   4063                     BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL;
   4064                 conf.inband_control.timer_mode &=
   4065                      (~bcmPortPhyTimesyncTimerMode80bit);
   4066                 conf.inband_control.timer_mode |= ( ibts_longts ) ?
   4067                        bcmPortPhyTimesyncTimerMode80bit : 0;
   4068             }
   4069 
   4070             conf.validity_mask =
   4071                 0xffffffff & ~BCM_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL;
   4072 
   4073             if ((rv =
   4074                  bcm_port_phy_timesync_config_set(u, p,
   4075                                                   &conf)) == BCM_E_FAIL) {
   4076                 cli_out("bcm_port_phy_timesync_config_set() "
   4077                         "failed, u=%d, p=%d\n", u, p);
   4078                 parse_arg_eq_done(&pt);
   4079                 return BCM_E_FAIL;
   4080             }
   4081             if (flags & (1U << 26)) {
   4082                 COMPILER_64_SET(val64, 0, 0xaaaaaaaa);
   4083                 rv = bcm_port_control_phy_timesync_set(u, p,
   4084                                                        bcmPortControlPhyTimesyncLoadControl,
   4085                                                        val64);
   4086                 if (rv != BCM_E_NONE) {
   4087                     cli_out("bcm_port_control_phy_timesync_set failed "
   4088                             "with error  u=%d p=%d %s\n",
   4089                             u, p, bcm_errmsg(rv));
   4090                 }
   4091             }
   4092             if (flags & (1U << 27)) {
   4093                 COMPILER_64_SET(val64, 0, 1);
   4094                 rv = bcm_port_control_phy_timesync_set(u, p,
   4095                                                        bcmPortControlPhyTimesyncFrameSync,
   4096                                                        val64);
   4097                 if (rv != BCM_E_NONE) {
   4098                     cli_out("bcm_port_control_phy_timesync_set failed "
   4099                             "with error  u=%d p=%d %s\n",
   4100                             u, p, bcm_errmsg(rv));
   4101                 }
   4102             }
   4103 
   4104         }
   4105 
   4106         /* free allocated memory from arg parsing */
   4107         parse_arg_eq_done(&pt);
   4108 
   4109     } else {
   4110 
   4111         /* coverity[overrun-local] */
   4112         DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   4113             int offset;
   4114 
   4115             /* coverity[unchecked_value] */
   4116             soc_phyctrl_offset_get(u, p, &offset);  /* return value not checked on purpose */
   4117 
   4118             cli_out("IEEE-1588 settings for %s(%03d) %s, offset=%d\n",
   4119                     SOC_PORT_NAME(u, p), p, soc_phy_name_get(u, p), offset);
   4120 
   4121             conf.validity_mask =
   4122                 0xffffffff & ~BCM_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL;
   4123             if ((rv =
   4124                  bcm_port_phy_timesync_config_get(u, p,
   4125                                                   &conf)) == BCM_E_FAIL) {
   4126                 cli_out("bcm_port_phy_timesync_config_get() "
   4127                         "failed, u=%d, p=%d\n", u, p);
   4128                 return BCM_E_FAIL;
   4129             }
   4130             _print_timesync_config(&conf);
   4131             _print_inband_timesync_config(&conf);
   4132             _print_heartbeat_ts(u, p);
   4133             _print_capture_ts(u, p);
   4134             /*_print_enhanced_capture(u, p);*/
   4135         }
   4136 
   4137     }
   4138     return CMD_OK;
   4139 }
   4140 
   4141 #ifdef INCLUDE_PHY_SYM_DBG
   4142 /* 
   4143  * Interface to PHY GUI for debugging 
   4144  */
   4145 /*
   4146  * MDIO Message format
   4147  */
   4148 typedef struct phy_sym_dbg_mdio_msg_s {
   4149     uint8 op;
   4150     uint8 port_id;
   4151     uint8 device;
   4152     uint8 c45;
   4153     uint16 reg_addr;
   4154     uint16 data;
   4155 } phy_sym_dbg_mdio_msg_t;
   4156 
   4157 enum phy_sum_dbg_mdio_op {
   4158     MDIO_HANDSHAKE,
   4159     MDIO_WRITE,
   4160     MDIO_READ,
   4161     MDIO_RESP,
   4162     MDIO_ERROR,
   4163     MDIO_CLOSE
   4164 };
   4165 #define PHY_SYM_DBG_MDIO_MSG_LEN sizeof(phy_sym_dbg_mdio_msg_t)
   4166 
   4167 typedef struct sym_dbg_s {
   4168     int unit;
   4169     int tcpportnum;
   4170     sal_mutex_t sym_dbg_lock;
   4171     int flags;
   4172 } sym_dbg_t;
   4173 
   4174 sym_dbg_t sym_dbg_arg;
   4175 
   4176 #define SYM_DBG_LOCK(sym_dbg_arg) sal_mutex_take(sym_dbg_arg.sym_dbg_lock, \
   4177                                                          sal_mutex_FOREVER)
   4178 #define SYM_DBG_UNLOCK(sym_dbg_arg) sal_mutex_give(sym_dbg_arg.sym_dbg_lock)
   4179 
   4180 #define SYM_DBG_THREAD_START 1
   4181 #define SYM_DBG_THREAD_STOP  2
   4182 
   4183 #define PHY_SYM_DBG_DEBUG_PRINT  0
   4184 
   4185 static void
   4186 _phy_sym_debug_server(void *unit)
   4187 {
   4188     int sockfd, newsockfd, clilen;
   4189     struct sockaddr_in serv_addr, client_addr;
   4190     phy_sym_dbg_mdio_msg_t buffer, mdio_rsp;
   4191     uint16 phy_data, reg_addr, data;
   4192     int n, rv = 0;
   4193     int u, tcpportno;
   4194     int flags = 0;
   4195     struct timeval tout;
   4196     fd_set sock_fdset;
   4197     int i;
   4198 
   4199     /* Not yet initialized */
   4200     SYM_DBG_LOCK(sym_dbg_arg);
   4201     flags = sym_dbg_arg.flags;
   4202     SYM_DBG_UNLOCK(sym_dbg_arg);
   4203 
   4204     if (!(flags & SYM_DBG_THREAD_START)) {
   4205         sal_thread_exit(-1);
   4206     }
   4207 
   4208     u = sym_dbg_arg.unit;
   4209     tcpportno = sym_dbg_arg.tcpportnum;
   4210 
   4211     sockfd = socket(AF_INET, SOCK_STREAM, 0);
   4212     if (sockfd < 0) {
   4213         cli_out("Error opeing a socket\n");
   4214         sal_thread_exit(-1);
   4215     }
   4216     bzero((char *)&serv_addr, sizeof(serv_addr));
   4217     serv_addr.sin_family = AF_INET;
   4218     serv_addr.sin_addr.s_addr = INADDR_ANY;
   4219     serv_addr.sin_port = htons(tcpportno);
   4220 
   4221     if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
   4222         cli_out("Error: socket bind falied\n");
   4223         close(sockfd);
   4224         sal_thread_exit(-1);
   4225     }
   4226     cli_out("Listening on the port %d for client connection\n", tcpportno);
   4227 
   4228     listen(sockfd, 1);
   4229     clilen = sizeof(client_addr);
   4230     cli_out("accepting on the socket %d for client connection\n", sockfd);
   4231 
   4232     while (1) {
   4233         FD_ZERO(&sock_fdset);
   4234         FD_SET(sockfd, &sock_fdset);
   4235         newsockfd = -1;
   4236         do {
   4237 #if PHY_SYM_DBG_DEBUG_PRINT
   4238             cli_out("Calling select\n");
   4239 #endif
   4240 
   4241             tout.tv_sec = 20;   /* 5 seconds */
   4242             tout.tv_usec = 0;
   4243             newsockfd = select(FD_SETSIZE, 
   4244                                &sock_fdset, &sock_fdset, NULL, &tout);
   4245 
   4246 #if PHY_SYM_DBG_DEBUG_PRINT
   4247             cli_out("Returned from select %d\n", newsockfd);
   4248 #endif
   4249             SYM_DBG_LOCK(sym_dbg_arg);
   4250             if (sym_dbg_arg.flags & SYM_DBG_THREAD_STOP) {
   4251                 cli_out("Closing Socket, user aborted\n");
   4252                 close(sockfd);
   4253                 sal_thread_exit(-1);
   4254             }
   4255             SYM_DBG_UNLOCK(sym_dbg_arg);
   4256         } while (newsockfd <= 0);
   4257 
   4258 #if PHY_SYM_DBG_DEBUG_PRINT
   4259         cli_out("Select returned \n");
   4260 #endif
   4261         newsockfd = accept(sockfd, (struct sockaddr *)&client_addr,
   4262                            (socklen_t *) & clilen);
   4263         if (newsockfd < 0) {
   4264             cli_out("Error in socket accept \n");
   4265             close(sockfd);
   4266             sal_thread_exit(-1);
   4267         }
   4268 #if PHY_SYM_DBG_DEBUG_PRINT
   4269         cli_out("Accepted Client connection %d\n", newsockfd);
   4270 #endif
   4271 
   4272 #if 0
   4273         bzero(&buffer, PHY_SYM_DBG_MDIO_MSG_LEN);
   4274         n = recv(newsockfd, &buffer, PHY_SYM_DBG_MDIO_MSG_LEN, 0);
   4275         if ((n < 0) || (n < PHY_SYM_DBG_MDIO_MSG_LEN)) {
   4276             cli_out("Error reading from socket \n");
   4277             rv = -1;
   4278             goto sock_close;
   4279         }
   4280         if (buffer.op != MDIO_HANDSHAKE) {
   4281             cli_out("Unknown connection, Handshake not "
   4282                     "received: Closing Socket\n");
   4283             rv = -1;
   4284             goto sock_close;
   4285         }
   4286 
   4287         /* Sending back the handshake */
   4288         bzero(&mdio_rsp, PHY_SYM_DBG_MDIO_MSG_LEN);
   4289         mdio_rsp.op = MDIO_HANDSHAKE;
   4290         n = send(newsockfd, &mdio_rsp, PHY_SYM_DBG_MDIO_MSG_LEN, 0);
   4291         if (n < 0) {
   4292             cli_out("Handshake:Error writing to socket\n");
   4293             rv = -1;
   4294             goto sock_close;
   4295         }
   4296         cli_out("Handshake with client completed\n");
   4297 #endif
   4298         while (1) {
   4299             /* Check if the thread needs to be aborted */
   4300             SYM_DBG_LOCK(sym_dbg_arg);
   4301             if (sym_dbg_arg.flags & SYM_DBG_THREAD_STOP) {
   4302                 break;
   4303             }
   4304             SYM_DBG_UNLOCK(sym_dbg_arg);
   4305             bzero((char *)&buffer, PHY_SYM_DBG_MDIO_MSG_LEN);
   4306             n = recv(newsockfd, (void *)&buffer, PHY_SYM_DBG_MDIO_MSG_LEN, 0);
   4307 #if PHY_SYM_DBG_DEBUG_PRINT
   4308             cli_out("Size read %d %d\n", n, PHY_SYM_DBG_MDIO_MSG_LEN);
   4309 #endif
   4310             if (n > 0) {
   4311                 for (i = 0; i < n; i++) {
   4312 #if PHY_SYM_DBG_DEBUG_PRINT
   4313                     cli_out("%x ", *(((char *)&buffer) + i));
   4314 #endif
   4315                 }
   4316             }
   4317             if ((n < 0) || (n < PHY_SYM_DBG_MDIO_MSG_LEN)) {
   4318                 cli_out("MDIO message corrupted or garbage read"
   4319                         " from socket: Closing socket\n");
   4320                 break;
   4321             }
   4322             reg_addr = ntohs(buffer.reg_addr);
   4323             data = ntohs(buffer.data);
   4324 
   4325             bzero((char *)&mdio_rsp, PHY_SYM_DBG_MDIO_MSG_LEN);
   4326             if (buffer.op == MDIO_WRITE) {
   4327 #if PHY_SYM_DBG_DEBUG_PRINT
   4328                 cli_out("MDIO WRITE operation\n");
   4329                 cli_out("%x %x %x %x %x\n", buffer.port_id, buffer.device,
   4330                         reg_addr, buffer.c45, data);
   4331 #endif
   4332                 if (buffer.c45) {
   4333                     rv = soc_miimc45_write(u, buffer.port_id, buffer.device,
   4334                                            reg_addr, data);
   4335                     /* Read the register */
   4336                     if (rv >= 0) {
   4337                         rv = soc_miimc45_read(u, buffer.port_id, buffer.device,
   4338                                               reg_addr, &phy_data);
   4339                     }
   4340                 } else {
   4341                     rv = soc_miim_write(u, buffer.port_id, reg_addr, data);
   4342                     /* Read the register */
   4343                     if (rv >= 0) {
   4344                         rv = soc_miim_read(u, buffer.port_id, reg_addr,
   4345                                            &phy_data);
   4346 #if PHY_SYM_DBG_DEBUG_PRINT
   4347                         cli_out("read data = %x\n", phy_data);
   4348 #endif
   4349                     }
   4350                 }
   4351                 if (rv < 0) {
   4352                     cli_out("ERROR: MII Addr %d: soc_miim_write failed: %s\n",
   4353                             buffer.port_id, soc_errmsg(rv));
   4354                     rv = -1;
   4355                     break;
   4356                 }
   4357                 mdio_rsp.data = htons(phy_data);
   4358                 mdio_rsp.op = MDIO_RESP;
   4359             } else {
   4360                 if (buffer.op == MDIO_READ) {
   4361 #if PHY_SYM_DBG_DEBUG_PRINT
   4362                     cli_out("MDIO READ operation\n");
   4363                     cli_out("%x %x %x %x %x\n", buffer.port_id, buffer.device,
   4364                             reg_addr, buffer.c45, data);
   4365 #endif
   4366 
   4367                     if (buffer.c45) {
   4368                         rv = soc_miimc45_read(u, buffer.port_id, buffer.device,
   4369                                               reg_addr, &phy_data);
   4370                     } else {
   4371                         rv = soc_miim_read(u, buffer.port_id, reg_addr,
   4372                                            &phy_data);
   4373                     }
   4374                     if (rv < 0) {
   4375                         cli_out("ERROR: MII Addr %d: soc_miim_read failed: %s\n",
   4376                                 buffer.port_id, soc_errmsg(rv));
   4377                         rv = -1;
   4378                         break;
   4379                     }
   4380                     mdio_rsp.data = htons(phy_data);
   4381                     mdio_rsp.op = MDIO_RESP;
   4382 #if PHY_SYM_DBG_DEBUG_PRINT
   4383                     cli_out("READ data = %x %x\n", mdio_rsp.data, phy_data);
   4384 #endif
   4385                 } else {
   4386                     if (buffer.op == MDIO_CLOSE) {
   4387                         cli_out("Closing connection\n");
   4388                         break;
   4389                     } else {
   4390                         cli_out("Unknown MDIO operation\n");
   4391                         mdio_rsp.op = MDIO_ERROR;
   4392                     }
   4393                 }
   4394             }
   4395 #if PHY_SYM_DBG_DEBUG_PRINT
   4396             cli_out("sending response:\n");
   4397             for (i = 0; i < n; i++) {
   4398                 cli_out("%x ", *(((char *)&mdio_rsp) + i));
   4399             }
   4400 #endif
   4401             n = send(newsockfd, (void *)&mdio_rsp, PHY_SYM_DBG_MDIO_MSG_LEN, 0);
   4402             if (n < 0) {
   4403 #if PHY_SYM_DBG_DEBUG_PRINT
   4404                 cli_out("Error writing to socket\n");
   4405 #endif
   4406                 rv = -1;
   4407                 break;
   4408             }
   4409         }
   4410     }
   4411 /*sock_close:*/
   4412     close(newsockfd);
   4413     close(sockfd);
   4414     sal_thread_exit(rv);
   4415 }
   4416 
   4417 STATIC cmd_result_t
   4418 _if_esw_phy_symdebug(int u, args_t *a)
   4419 {
   4420     int portnum;
   4421     sal_thread_t sym_dbg_thread;
   4422     char *c;
   4423 
   4424     if (sym_dbg_arg.flags == SYM_DBG_THREAD_START) {
   4425         cli_out("Thread already running\n");
   4426         return CMD_OK;
   4427     }
   4428 
   4429     /* Get TCP port number to listen on */
   4430     if ((c = ARG_GET(a)) == NULL) {
   4431         return CMD_USAGE;
   4432     }
   4433     portnum = sal_ctoi(c, 0);
   4434 
   4435     cli_out("Entering PHY Symbolic Debug mode. In this mode the link scan "
   4436             "is DISABLED\n");
   4437     cli_out("Listening on TCP port %d\n", portnum);
   4438 
   4439     sym_dbg_arg.unit = u;
   4440     sym_dbg_arg.tcpportnum = portnum;
   4441     sym_dbg_arg.flags = SYM_DBG_THREAD_START;
   4442     sym_dbg_arg.sym_dbg_lock = sal_mutex_create("sym_dbg_lock");
   4443 
   4444     /* Create a thread to execute the sock functions */
   4445     sym_dbg_thread = sal_thread_create("phy_sym_dbg", 0, SAL_THREAD_STKSZ,
   4446                                        _phy_sym_debug_server, (void *)&u);
   4447     if (sym_dbg_thread == NULL) {
   4448         cli_out("Unable to create thread\n");
   4449         return CMD_FAIL;
   4450     }
   4451     return CMD_OK;
   4452 }
   4453 
   4454 STATIC cmd_result_t
   4455 _if_esw_phy_symdebug_off(int u, args_t *a)
   4456 {
   4457     cli_out("Stopping server thread\n");
   4458     SYM_DBG_LOCK(sym_dbg_arg);
   4459     sym_dbg_arg.flags = SYM_DBG_THREAD_STOP;
   4460     SYM_DBG_UNLOCK(sym_dbg_arg);
   4461     return CMD_OK;
   4462 }
   4463 #endif
   4464 
   4465 STATIC cmd_result_t
   4466 _if_esw_phy_firmware(int u, args_t *a)
   4467 {
   4468 #ifdef  NO_FILEIO
   4469     cli_out("This command is not supported without file I/O\n");
   4470     return CMD_FAIL;
   4471 #else
   4472     soc_pbmp_t pbm;
   4473     soc_port_t p, dport;
   4474     char *c;
   4475     int rv = 0;
   4476     parse_table_t pt;
   4477     int count;
   4478     FILE *fp = NULL;
   4479     uint8 *buf;
   4480     int buf_len;
   4481     int len;
   4482     uint32 flags;
   4483     char input[32];
   4484     int no_confirm = FALSE;
   4485     int internal = 0;
   4486     int raw = 0;
   4487     char *filename = NULL;
   4488 
   4489     if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) {
   4490         cli_out("%s: ERROR: unrecognized port bitmap: %s\n",
   4491                 ARG_CMD(a), c ? c : "");
   4492         return CMD_FAIL;
   4493     }
   4494 
   4495     SOC_PBMP_COUNT(pbm, count);
   4496 
   4497     if (count > 1) {
   4498         cli_out("ERROR: too many ports specified : %d\n",
   4499                 count);
   4500         return CMD_FAIL;
   4501     }
   4502     parse_table_init(u, &pt);
   4503     if ((c = ARG_CUR(a)) != NULL) {
   4504 
   4505         if (c[0] == '=') {
   4506             return CMD_USAGE;       /* '=' unsupported */
   4507         }
   4508 
   4509         parse_table_add(&pt, "set", PQ_DFL | PQ_STRING, 0,
   4510                         &filename, NULL);
   4511         parse_table_add(&pt, "-y", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 0,
   4512                         &no_confirm, NULL);
   4513         parse_table_add(&pt, "int", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 0,
   4514                         &internal, NULL);
   4515         parse_table_add(&pt, "raw", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 0,
   4516                         &raw, NULL);
   4517 
   4518         if (parse_arg_eq(a, &pt) < 0) {
   4519             parse_arg_eq_done(&pt);
   4520             return CMD_USAGE;
   4521         }
   4522         if (ARG_CNT(a) > 0) {
   4523             cli_out("%s: Unknown argument %s\n",
   4524                     ARG_CMD(a), ARG_CUR(a));
   4525             parse_arg_eq_done(&pt);
   4526             return CMD_USAGE;
   4527         }
   4528     }
   4529 
   4530     if (!filename) {
   4531         cli_out("ERROR: file name missing\n");
   4532         parse_arg_eq_done(&pt);
   4533         return CMD_USAGE;
   4534     }
   4535 
   4536     if (raw && !internal) {
   4537         cli_out("ERROR: raw mode supported for internal PHYs only\n");
   4538         parse_arg_eq_done(&pt);
   4539         return CMD_FAIL;
   4540     }
   4541 
   4542     if ((fp = sal_fopen(filename, "rb")) == NULL) {
   4543         cli_out("ERROR: Can't open the file : %s\n",
   4544                 filename);
   4545         parse_arg_eq_done(&pt);
   4546         return CMD_FAIL;
   4547     }
   4548 
   4549     ;
   4550     if ((buf_len = sal_fsize(fp)) <= 0) {
   4551         cli_out("ERROR: Could not determine file size\n");
   4552         parse_arg_eq_done(&pt);
   4553         sal_fclose(fp);
   4554         return CMD_FAIL;
   4555     }
   4556 
   4557     /*
   4558      * filename points to memory allocated by arg parsing.
   4559      * Calling parse_arg_eq_done frees this memory.
   4560      */
   4561     parse_arg_eq_done(&pt);
   4562 
   4563     if (!raw && !no_confirm) {
   4564         /* prompt user for confirmation */
   4565         cli_out("Warning!!!\n"
   4566                 "The PHY device may become un-usable if the power is off\n"
   4567                 "during this process or a wrong file is given. The file must\n"
   4568                 "be in BINARY format. The only way to recover is to program\n"
   4569                 "the non-volatile storage device with a rom burner\n");
   4570 
   4571         if ((NULL ==
   4572              sal_readline("Are you sure you want to continue (yes/[no])?",
   4573                           input, sizeof(input), "no")) ||
   4574             (sal_strlen(input) != sal_strlen("yes")) ||
   4575             (sal_strncasecmp("yes", input, sal_strlen(input)))) {
   4576             sal_fclose(fp);
   4577             cli_out("Firmware update aborted. No writes to the "
   4578                     "PHY device's non-volatile storage\n");
   4579             return CMD_FAIL;
   4580         }
   4581     }
   4582 
   4583     buf = sal_alloc(buf_len, "temp_buf");
   4584     if (buf == NULL) {
   4585         sal_fclose(fp);
   4586         cli_out("ERROR: Cannot allocate enough buffer space: %d\n",
   4587                 buf_len);
   4588         return CMD_FAIL;
   4589     }
   4590 
   4591     /* coverity[overrun-local] */
   4592     DPORT_BCM_PBMP_ITER(u, pbm, dport, p) {
   4593         /*    coverity[tainted_data_argument]    */
   4594         len = sal_fread(buf, 1, buf_len, fp);
   4595         if (len != buf_len) {
   4596             sal_fclose(fp);
   4597             /* coverity[tainted_data] */
   4598             sal_free(buf);
   4599             cli_out("ERROR: Could only read %d bytes (out of %d)\n",
   4600                     len, buf_len);
   4601             return CMD_FAIL;
   4602         }
   4603         cli_out("Downloading %d bytes...\n", len);
   4604         flags = internal ? BCM_PORT_PHY_INTERNAL : 0;
   4605         if (raw) {
   4606             rv = soc_phy_firmware_load(u, p, buf, len);
   4607         } else {
   4608             rv = bcm_port_phy_firmware_set(u, p, flags, 0, buf, len);
   4609         }
   4610         break;
   4611     }
   4612     sal_fclose(fp);
   4613     /*    coverity[tainted_data]    */
   4614     sal_free(buf);
   4615     if (rv == SOC_E_NONE) {
   4616         cli_out("Successfully done!!!\n");
   4617     } else if (rv == SOC_E_UNAVAIL) {
   4618         cli_out("Aborted.\n"
   4619                 "Feature is not available for this PHY device.\n");
   4620     } else {
   4621         cli_out("Failed (%s).\n",
   4622                 bcm_errmsg(rv));
   4623         if (!raw) {
   4624             cli_out("PHY device may not be usable.\n");
   4625         }
   4626     }
   4627     return CMD_OK;
   4628 #endif
   4629 }
   4630 
   4631 STATIC cmd_result_t
   4632 _if_esw_phy_oam(int u, args_t *a)
   4633 {
   4634     soc_pbmp_t pbm;
   4635     soc_port_t p, dport;
   4636     char *c;
   4637     int i, rv = 0;
   4638     bcm_port_config_phy_oam_t conf;
   4639     uint64 val64;
   4640 
   4641     sal_memset(&conf, 0, sizeof(bcm_port_config_phy_oam_t));
   4642     COMPILER_64_SET(val64, 0, 0);
   4643 
   4644     if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) {
   4645         cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c);
   4646         return CMD_FAIL;
   4647     }
   4648     if ((c = ARG_CUR(a)) != NULL) {
   4649         parse_table_t pt;
   4650         uint32 mac_addr_hi = 0, mac_addr_low = 0, flags;
   4651         uint32 mac_addr_hi_1 = 0, mac_addr_low_1 = 0;
   4652         uint32 mac_addr_hi_2 = 0, mac_addr_low_2 = 0;
   4653         uint32 mac_addr_hi_3 = 0, mac_addr_low_3 = 0;
   4654         uint32 eth_type = 0;
   4655         uint32 mac_check_en = 0, cw_en = 0, entropy_en = 0,
   4656             mac_index = 0, timestamp = 0;
   4657         char *mode, *dir, *ts_format;
   4658         uint8 tx = 0, rx = 0, oam_mode;
   4659         uint32 type;
   4660 
   4661         parse_table_init(u, &pt);
   4662         parse_table_add(&pt, "MODE", PQ_DFL | PQ_STRING, 0, &mode, 0);
   4663         parse_table_add(&pt, "DIR", PQ_DFL | PQ_STRING, 0, &dir, 0);
   4664         parse_table_add(&pt, "MacCheck", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   4665                         0, &mac_check_en, 0);
   4666         parse_table_add(&pt, "ControlWord", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   4667                         0, &cw_en, 0);
   4668         parse_table_add(&pt, "ENTROPY", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   4669                         0, &entropy_en, 0);
   4670         parse_table_add(&pt, "TimeStampFormat", PQ_DFL | PQ_STRING,
   4671                         0, &ts_format, 0);
   4672         parse_table_add(&pt, "ETHerType", PQ_INT | PQ_DFL, 0, &eth_type, 0);
   4673         parse_table_add(&pt, "MACIndex", PQ_INT | PQ_DFL, 0, &mac_index, 0);
   4674         parse_table_add(&pt, "MACAddrHi", PQ_INT | PQ_DFL,
   4675                         0, &mac_addr_hi, 0);
   4676         parse_table_add(&pt, "MACAddrLow", PQ_INT | PQ_DFL,
   4677                         0, &mac_addr_low, 0);
   4678         parse_table_add(&pt, "MACAddrHi1", PQ_INT | PQ_DFL,
   4679                         0, &mac_addr_hi_1, 0);
   4680         parse_table_add(&pt, "MACAddrLow1", PQ_INT | PQ_DFL,
   4681                         0, &mac_addr_low_1, 0);
   4682         parse_table_add(&pt, "MACAddrHi2", PQ_INT | PQ_DFL,
   4683                         0, &mac_addr_hi_2, 0);
   4684         parse_table_add(&pt, "MACAddrLow2", PQ_INT | PQ_DFL,
   4685                         0, &mac_addr_low_2, 0);
   4686         parse_table_add(&pt, "MACAddrHi3", PQ_INT | PQ_DFL,
   4687                         0, &mac_addr_hi_3, 0);
   4688         parse_table_add(&pt, "MACAddrLow3", PQ_INT | PQ_DFL,
   4689                         0, &mac_addr_low_3, 0);
   4690 
   4691         if (parse_arg_eq(a, &pt) < 0) {
   4692             parse_arg_eq_done(&pt);
   4693             return CMD_USAGE;
   4694         }
   4695         if (ARG_CNT(a) > 0) {
   4696             cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a));
   4697             parse_arg_eq_done(&pt);
   4698             return CMD_USAGE;
   4699         }
   4700 
   4701         flags = 0;
   4702 
   4703         for (i = 0; i < pt.pt_cnt; i++) {
   4704             if (pt.pt_entries[i].pq_type & PQ_PARSED) {
   4705                 flags |= (1 << i);
   4706             }
   4707         }
   4708 
   4709         DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   4710             if ((rv =
   4711                  bcm_port_config_phy_oam_get(u, p, &conf)) == BCM_E_FAIL) {
   4712                 cli_out("bcm_port_config_phy_oam_get() failed, u=%d, p=%d\n",
   4713                         u, p);
   4714                 parse_arg_eq_done(&pt);
   4715                 return CMD_FAIL;
   4716             }
   4717 
   4718             if (flags & (1U << 1)) {
   4719                 if (!sal_strcmp(dir, "tx")) {
   4720                     tx = 1;
   4721                 } else if (!sal_strcmp(dir, "rx")) {
   4722                     rx = 1;
   4723                 } else {
   4724                     parse_arg_eq_done(&pt);
   4725                     return CMD_USAGE;
   4726                 }
   4727             } else {
   4728                 tx = 1;
   4729                 rx = 1;
   4730             }
   4731 
   4732             if (flags & (1U << 0)) {
   4733                 if (!sal_strcmp(mode, "y1731")) {
   4734                     oam_mode = bcmPortConfigPhyOamDmModeY1731;
   4735                 } else if (!sal_strcmp(mode, "bhh")) {
   4736                     oam_mode = bcmPortConfigPhyOamDmModeBhh;
   4737                 } else if (!sal_strcmp(mode, "ietf")) {
   4738                     oam_mode = bcmPortConfigPhyOamDmModeIetf;
   4739                 } else {
   4740                     parse_arg_eq_done(&pt);
   4741                     return CMD_USAGE;
   4742                 }
   4743 
   4744                 if (tx) {
   4745                     conf.tx_dm_config.mode = oam_mode;
   4746                 }
   4747                 if (rx) {
   4748                     conf.rx_dm_config.mode = oam_mode;
   4749                 }
   4750             }
   4751 
   4752             if (flags & (1U << 2)) {
   4753                 if (tx) {
   4754                     conf.tx_dm_config.flags &=
   4755                         ~BCM_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE;
   4756                     conf.tx_dm_config.flags |=
   4757                         mac_check_en ? BCM_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE
   4758                         : 0;
   4759                 }
   4760                 if (rx) {
   4761                     conf.rx_dm_config.flags &=
   4762                         ~BCM_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE;
   4763                     conf.rx_dm_config.flags |=
   4764                         mac_check_en ? BCM_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE
   4765                         : 0;
   4766                 }
   4767             }
   4768             if (flags & (1U << 3)) {
   4769                 if (tx) {
   4770                     conf.tx_dm_config.flags &=
   4771                         ~BCM_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE;
   4772                     conf.tx_dm_config.flags |=
   4773                         cw_en ? BCM_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE : 0;
   4774                 }
   4775                 if (rx) {
   4776                     conf.rx_dm_config.flags &=
   4777                         ~BCM_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE;
   4778                     conf.rx_dm_config.flags |=
   4779                         cw_en ? BCM_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE : 0;
   4780                 }
   4781             }
   4782             if (flags & (1U << 4)) {
   4783                 if (tx) {
   4784                     conf.tx_dm_config.flags &=
   4785                         ~BCM_PORT_PHY_OAM_DM_ENTROPY_ENABLE;
   4786                     conf.tx_dm_config.flags |=
   4787                         entropy_en ? BCM_PORT_PHY_OAM_DM_ENTROPY_ENABLE : 0;
   4788                 }
   4789                 if (rx) {
   4790                     conf.rx_dm_config.flags &=
   4791                         ~BCM_PORT_PHY_OAM_DM_ENTROPY_ENABLE;
   4792                     conf.rx_dm_config.flags |=
   4793                         entropy_en ? BCM_PORT_PHY_OAM_DM_ENTROPY_ENABLE : 0;
   4794                 }
   4795             }
   4796             if (flags & (1U << 5)) {
   4797                 if (!sal_strcmp(ts_format, "ntp")) {
   4798                     timestamp = 1;
   4799                 } else if (!sal_strcmp(ts_format, "ptp")) {
   4800                     timestamp = 0;
   4801                 } else {
   4802                     parse_arg_eq_done(&pt);
   4803                     return CMD_USAGE;
   4804                 }
   4805 
   4806                 if (tx) {
   4807                     conf.tx_dm_config.flags &=
   4808                         ~BCM_PORT_PHY_OAM_DM_TS_FORMAT;
   4809                     conf.tx_dm_config.flags |=
   4810                         timestamp ? BCM_PORT_PHY_OAM_DM_TS_FORMAT : 0;
   4811                 }
   4812                 if (rx) {
   4813                     conf.rx_dm_config.flags &=
   4814                         ~BCM_PORT_PHY_OAM_DM_TS_FORMAT;
   4815                     conf.rx_dm_config.flags |=
   4816                         timestamp ? BCM_PORT_PHY_OAM_DM_TS_FORMAT : 0;
   4817                 }
   4818             }
   4819 
   4820             /* CONFIG SET */
   4821             if ((rv =
   4822                  bcm_port_config_phy_oam_set(u, p, &conf)) == BCM_E_FAIL) {
   4823                 cli_out("bcm_port_config_phy_oam_set() failed, u=%d, p=%d\n",
   4824                         u, p);
   4825                 parse_arg_eq_done(&pt);
   4826                 return CMD_FAIL;
   4827             }
   4828 
   4829             if (flags & (1U << 6)) {
   4830                 COMPILER_64_SET(val64, 0, eth_type);
   4831                 if (tx) {
   4832                     rv = bcm_port_control_phy_oam_set(u, p,
   4833                                                       bcmPortControlPhyOamDmTxEthertype,
   4834                                                       val64);
   4835                     if (rv != BCM_E_NONE) {
   4836                         cli_out("bcm_port_control_phy_oam_set failed with error \
   4837                                 u=%d p=%d %s\n", u, p,
   4838                                 bcm_errmsg(rv));
   4839                         parse_arg_eq_done(&pt);
   4840                         return CMD_FAIL;
   4841                     }
   4842                 }
   4843                 if (rx) {
   4844                     rv = bcm_port_control_phy_oam_set(u, p,
   4845                                                       bcmPortControlPhyOamDmRxEthertype,
   4846                                                       val64);
   4847                     if (rv != BCM_E_NONE) {
   4848                         cli_out("bcm_port_control_phy_oam_set failed with error  \
   4849                                 u=%d p=%d %s\n", u, p,
   4850                                 bcm_errmsg(rv));
   4851                         parse_arg_eq_done(&pt);
   4852                         return CMD_FAIL;
   4853                     }
   4854                 }
   4855             }
   4856 
   4857             if (flags & (1U << 7)) {
   4858                 if (mac_index == 0) {
   4859                     parse_arg_eq_done(&pt);
   4860                     return CMD_USAGE;
   4861                 }
   4862                 COMPILER_64_SET(val64, 0, mac_index);
   4863                 if (tx) {
   4864                     rv = bcm_port_control_phy_oam_set(u, p,
   4865                                                       bcmPortControlPhyOamDmTxPortMacAddressIndex,
   4866                                                       val64);
   4867                     if (rv != BCM_E_NONE) {
   4868                         cli_out("bcm_port_control_phy_oam_set failed with error  \
   4869                                 u=%d p=%d %s\n", u, p,
   4870                                 bcm_errmsg(rv));
   4871                         parse_arg_eq_done(&pt);
   4872                         return CMD_FAIL;
   4873                     }
   4874                 }
   4875                 if (rx) {
   4876                     rv = bcm_port_control_phy_oam_set(u, p,
   4877                                                       bcmPortControlPhyOamDmRxPortMacAddressIndex,
   4878                                                       val64);
   4879                     if (rv != BCM_E_NONE) {
   4880                         cli_out("bcm_port_control_phy_oam_set failed with error  \
   4881                                 u=%d p=%d %s\n", u, p,
   4882                                 bcm_errmsg(rv));
   4883                         parse_arg_eq_done(&pt);
   4884                         return CMD_FAIL;
   4885                     }
   4886                 }
   4887             }
   4888             /* If mac_index is not provided and mac_addr needs to be set
   4889                use mac_addr_1/2/3 instead.
   4890              */
   4891             if (!(flags & (1U << 7)) &&
   4892                 ((flags & (1U << 8)) || (flags & (1U << 9)))) {
   4893                 cli_out(" MACAddrHi/MACAddrLow cannot be used without 'MACIndex. "
   4894                         "Please use MACAddrHi1/2/3 for updating MAC address\n");
   4895                 parse_arg_eq_done(&pt);
   4896                 return CMD_FAIL;
   4897             }
   4898             if ((flags & (1U << 8)) || (flags & (1U << 9))) {
   4899                 switch (mac_index) {
   4900                     case 1:
   4901                         type = bcmPortControlPhyOamDmMacAddress1;
   4902                         break;
   4903                     case 2:
   4904                         type = bcmPortControlPhyOamDmMacAddress2;
   4905                         break;
   4906                     case 3:
   4907                         type = bcmPortControlPhyOamDmMacAddress3;
   4908                         break;
   4909                     default:
   4910                         parse_arg_eq_done(&pt);
   4911                         return CMD_FAIL;
   4912                 }
   4913 
   4914                 COMPILER_64_SET(val64, mac_addr_hi, mac_addr_low);
   4915 
   4916                 rv = bcm_port_control_phy_oam_set(u, p, type, val64);
   4917                 if (rv != BCM_E_NONE) {
   4918                     cli_out("bcm_port_control_phy_oam_set failed with error  \
   4919                             u=%d p=%d %s\n", u, p,
   4920                             bcm_errmsg(rv));
   4921                     parse_arg_eq_done(&pt);
   4922                     return CMD_FAIL;
   4923                 }
   4924             }
   4925             if ((flags & (1U << 10)) || (flags & (1U << 11))) {
   4926                 COMPILER_64_SET(val64, mac_addr_hi_1, mac_addr_low_1);
   4927 
   4928                 rv = bcm_port_control_phy_oam_set(u, p,
   4929                                                   bcmPortControlPhyOamDmMacAddress1,
   4930                                                   val64);
   4931                 if (rv != BCM_E_NONE) {
   4932                     cli_out("bcm_port_control_phy_oam_set failed with error  \
   4933                             u=%d p=%d %s\n", u, p,
   4934                             bcm_errmsg(rv));
   4935                     parse_arg_eq_done(&pt);
   4936                     return CMD_FAIL;
   4937                 }
   4938             }
   4939             if ((flags & (1U << 12)) || (flags & (1U << 13))) {
   4940                 COMPILER_64_SET(val64, mac_addr_hi_2, mac_addr_low_2);
   4941 
   4942                 rv = bcm_port_control_phy_oam_set(u, p,
   4943                                                   bcmPortControlPhyOamDmMacAddress2,
   4944                                                   val64);
   4945                 if (rv != BCM_E_NONE) {
   4946                     cli_out("bcm_port_control_phy_oam_set failed with error  \
   4947                             u=%d p=%d %s\n", u, p,
   4948                             bcm_errmsg(rv));
   4949                     parse_arg_eq_done(&pt);
   4950                     return CMD_FAIL;
   4951                 }
   4952             }
   4953             if ((flags & (1U << 14)) || (flags & (1U << 15))) {
   4954                 COMPILER_64_SET(val64, mac_addr_hi_3, mac_addr_low_3);
   4955 
   4956                 rv = bcm_port_control_phy_oam_set(u, p,
   4957                                                   bcmPortControlPhyOamDmMacAddress3,
   4958                                                   val64);
   4959                 if (rv != BCM_E_NONE) {
   4960                     cli_out("bcm_port_control_phy_oam_set failed with error  \
   4961                             u=%d p=%d %s\n", u, p,
   4962                             bcm_errmsg(rv));
   4963                     parse_arg_eq_done(&pt);
   4964                     return CMD_FAIL;
   4965                 }
   4966             }
   4967 
   4968         }
   4969         /* free allocated memory from arg parsing */
   4970         parse_arg_eq_done(&pt);
   4971 
   4972     } else {
   4973 
   4974         /* coverity[overrun-local] */
   4975         DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   4976             int offset;
   4977             uint64 tx_ethtype, rx_ethtype;
   4978             uint64 mac1, mac2, mac3;
   4979             uint64 tx_mac_index, rx_mac_index;
   4980 
   4981             COMPILER_64_SET(tx_ethtype, 0, 0);
   4982             COMPILER_64_SET(rx_ethtype, 0, 0);
   4983             COMPILER_64_SET(mac1, 0, 0);
   4984             COMPILER_64_SET(mac2, 0, 0);
   4985             COMPILER_64_SET(mac3, 0, 0);
   4986             COMPILER_64_SET(tx_mac_index, 0, 0);
   4987             COMPILER_64_SET(rx_mac_index, 0, 0);
   4988             /* coverity[unchecked_value] */
   4989             soc_phyctrl_offset_get(u, p, &offset);  /* return value not checked on purpose */
   4990 
   4991             cli_out("\n\nOAM settings for %s(%3d) %s, offset = %d\n\n",
   4992                     SOC_PORT_NAME(u, p), p, soc_phy_name_get(u, p), offset);
   4993 
   4994             if ((rv =
   4995                  bcm_port_config_phy_oam_get(u, p, &conf)) == BCM_E_FAIL) {
   4996                 cli_out("bcm_port_config_phy_oam_get() failed, u=%d, p=%d\n",
   4997                         u, p);
   4998                 return CMD_FAIL;
   4999             }
   5000 
   5001             rv = bcm_port_control_phy_oam_get(u, p,
   5002                                               bcmPortControlPhyOamDmTxEthertype,
   5003                                               &tx_ethtype);
   5004             if (rv != BCM_E_NONE) {
   5005                 cli_out("bcm_port_control_phy_oam_get (TxEthertype) failed with error \
   5006                         u=%d p=%d %s\n", u, p,
   5007                         bcm_errmsg(rv));
   5008                 return CMD_FAIL;
   5009             }
   5010             rv = bcm_port_control_phy_oam_get(u, p,
   5011                                               bcmPortControlPhyOamDmRxEthertype,
   5012                                               &rx_ethtype);
   5013             if (rv != BCM_E_NONE) {
   5014                 cli_out("bcm_port_control_phy_oam_get (RxEthertype) failed with error  \
   5015                         u=%d p=%d %s\n", u, p,
   5016                         bcm_errmsg(rv));
   5017                 return CMD_FAIL;
   5018             }
   5019             rv = bcm_port_control_phy_oam_get(u, p,
   5020                                               bcmPortControlPhyOamDmTxPortMacAddressIndex,
   5021                                               &tx_mac_index);
   5022             if (rv != BCM_E_NONE) {
   5023                 cli_out("bcm_port_control_phy_oam_get (TxMACIndex)failed with error  \
   5024                         u=%d p=%d %s\n", u, p,
   5025                         bcm_errmsg(rv));
   5026                 return CMD_FAIL;
   5027             }
   5028             rv = bcm_port_control_phy_oam_get(u, p,
   5029                                               bcmPortControlPhyOamDmRxPortMacAddressIndex,
   5030                                               &rx_mac_index);
   5031             if (rv != BCM_E_NONE) {
   5032                 cli_out("bcm_port_control_phy_oam_get (RxMACIndex)failed with error  \
   5033                         u=%d p=%d %s\n", u, p,
   5034                         bcm_errmsg(rv));
   5035                 return CMD_FAIL;
   5036             }
   5037 
   5038             rv = bcm_port_control_phy_oam_get(u, p,
   5039                                               bcmPortControlPhyOamDmMacAddress1,
   5040                                               &mac1);
   5041             if (rv != BCM_E_NONE) {
   5042                 cli_out("bcm_port_control_phy_oam_get (MacAddr1)failed with error  \
   5043                         u=%d p=%d %s\n", u, p,
   5044                         bcm_errmsg(rv));
   5045                 return CMD_FAIL;
   5046             }
   5047             rv = bcm_port_control_phy_oam_get(u, p,
   5048                                               bcmPortControlPhyOamDmMacAddress2,
   5049                                               &mac2);
   5050             if (rv != BCM_E_NONE) {
   5051                 cli_out("bcm_port_control_phy_oam_get (MacAddr2)failed with error  \
   5052                         u=%d p=%d %s\n", u, p,
   5053                         bcm_errmsg(rv));
   5054                 return CMD_FAIL;
   5055             }
   5056             rv = bcm_port_control_phy_oam_get(u, p,
   5057                                               bcmPortControlPhyOamDmMacAddress3,
   5058                                               &mac3);
   5059             if (rv != BCM_E_NONE) {
   5060                 cli_out("bcm_port_control_phy_oam_get (MacAddr3)failed with error  \
   5061                         u=%d p=%d %s\n", u, p,
   5062                         bcm_errmsg(rv));
   5063                 return CMD_FAIL;
   5064             }
   5065 
   5066             cli_out("\nPHY OAM TX Config Settings:\n");
   5067             cli_out("=============================\n");
   5068             cli_out("MODE (Y1731, BHH or IETF) - %s\n",
   5069                     (conf.tx_dm_config.mode ==
   5070                     bcmPortConfigPhyOamDmModeY1731) ? "Y.1731" : (conf.
   5071                     tx_dm_config.
   5072                     mode ==
   5073                     bcmPortConfigPhyOamDmModeBhh)
   5074                     ? "BHH" : (conf.tx_dm_config.mode ==
   5075                     bcmPortConfigPhyOamDmModeIetf) ? "IETF" :
   5076                     "NONE");
   5077             cli_out("MacCheck (Y or N) - %s\n",
   5078                     conf.tx_dm_config.
   5079                     flags & BCM_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE ? "Y" :
   5080                     "N");
   5081             cli_out("ControlWord (Y or N) - %s\n",
   5082                     conf.tx_dm_config.
   5083                     flags & BCM_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE ? "Y" :
   5084                     "N");
   5085             cli_out("ENTROPY (Y or N) - %s\n",
   5086                     conf.tx_dm_config.
   5087                     flags & BCM_PORT_PHY_OAM_DM_ENTROPY_ENABLE ? "Y" : "N");
   5088             cli_out("TimeStampFormat (PTP or NTP) - %s\n",
   5089                     conf.tx_dm_config.
   5090                     flags & BCM_PORT_PHY_OAM_DM_TS_FORMAT ? "NTP" : "PTP");
   5091             cli_out("EtherType- 0x%x\n", COMPILER_64_LO(tx_ethtype));
   5092             cli_out("MacIndex- %d\n", COMPILER_64_LO(tx_mac_index));
   5093 
   5094             cli_out("\nPHY OAM RX Config Settings:\n");
   5095             cli_out("=============================\n");
   5096             cli_out("MODE (Y1731, BHH or IETF) - %s\n",
   5097                     (conf.rx_dm_config.mode ==
   5098                     bcmPortConfigPhyOamDmModeY1731) ? "Y.1731" : (conf.
   5099                     rx_dm_config.
   5100                     mode ==
   5101                     bcmPortConfigPhyOamDmModeBhh)
   5102                     ? "BHH" : (conf.rx_dm_config.mode ==
   5103                     bcmPortConfigPhyOamDmModeIetf) ? "IETF" :
   5104                     "NONE");
   5105             cli_out("MacCheck (Y or N) - %s\n",
   5106                     conf.rx_dm_config.
   5107                     flags & BCM_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE ? "Y" :
   5108                     "N");
   5109             cli_out("ControlWord (Y or N) - %s\n",
   5110                     conf.rx_dm_config.
   5111                     flags & BCM_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE ? "Y" :
   5112                     "N");
   5113             cli_out("ENTROPY (Y or N) - %s\n",
   5114                     conf.rx_dm_config.
   5115                     flags & BCM_PORT_PHY_OAM_DM_ENTROPY_ENABLE ? "Y" : "N");
   5116             cli_out("TimeStampFormat (PTP or NTP) - %s\n",
   5117                     conf.rx_dm_config.
   5118                     flags & BCM_PORT_PHY_OAM_DM_TS_FORMAT ? "NTP" : "PTP");
   5119             cli_out("EtherType- 0x%x\n", COMPILER_64_LO(rx_ethtype));
   5120             cli_out("MacIndex- %d\n", COMPILER_64_LO(rx_mac_index));
   5121 
   5122             cli_out("\nOther Settings:\n");
   5123             cli_out("=============================\n");
   5124             cli_out("MAC Address 1 - 0x%08x%08x\n", COMPILER_64_HI(mac1),
   5125                     COMPILER_64_LO(mac1));
   5126             cli_out("MAC Address 2 - 0x%08x%08x\n", COMPILER_64_HI(mac2),
   5127                     COMPILER_64_LO(mac2));
   5128             cli_out("MAC Address 3 - 0x%08x%08x\n", COMPILER_64_HI(mac3),
   5129                     COMPILER_64_LO(mac3));
   5130 
   5131         }
   5132 
   5133     }
   5134     return CMD_OK;
   5135 }
   5136 
   5137 STATIC cmd_result_t
   5138 _if_esw_phy_power(int u, args_t *a)
   5139 {
   5140     soc_pbmp_t pbm;
   5141     soc_port_t p, dport;
   5142     char *c;
   5143     int rv = 0;
   5144     parse_table_t pt;
   5145     char *mode_type = 0;
   5146     uint32 mode_value;
   5147     int sleep_time = -1;
   5148     int wake_time = -1;
   5149 
   5150     if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) {
   5151         cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c);
   5152         return CMD_FAIL;
   5153     }
   5154 
   5155     if ((c = ARG_CUR(a)) != NULL) {
   5156 
   5157         if (c[0] == '=') {
   5158             return CMD_USAGE;       /* '=' unsupported */
   5159         }
   5160 
   5161         parse_table_init(u, &pt);
   5162         parse_table_add(&pt, "mode", PQ_DFL | PQ_STRING, 0,
   5163                         &mode_type, NULL);
   5164 
   5165         parse_table_add(&pt, "Sleep_Time", PQ_DFL | PQ_INT,
   5166                         0, &sleep_time, NULL);
   5167 
   5168         parse_table_add(&pt, "Wake_Time", PQ_DFL | PQ_INT,
   5169                         0, &wake_time, NULL);
   5170 
   5171         if (parse_arg_eq(a, &pt) < 0) {
   5172             parse_arg_eq_done(&pt);
   5173             return CMD_USAGE;
   5174         }
   5175         if (ARG_CNT(a) > 0) {
   5176             cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a));
   5177             parse_arg_eq_done(&pt);
   5178             return CMD_USAGE;
   5179         }
   5180     } else {
   5181         char *str;
   5182         cli_out("Phy Power Mode dump:\n");
   5183         cli_out("%10s %16s %14s %14s %14s\n",
   5184                 "port", "name", "power_mode", "sleep_time(ms)",
   5185                 "wake_time(ms)");
   5186         /* coverity[overrun-local] */
   5187         DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   5188             mode_value = 0;
   5189             sleep_time = 0;
   5190             wake_time = 0;
   5191             rv = bcm_port_phy_control_get(u, p, BCM_PORT_PHY_CONTROL_POWER,
   5192                                           &mode_value);
   5193             if (rv == SOC_E_NONE) {
   5194                 if (mode_value == BCM_PORT_PHY_CONTROL_POWER_AUTO) {
   5195                     str = "auto_down";
   5196                     if ((rv = bcm_port_phy_control_get(u, p,
   5197                                                        BCM_PORT_PHY_CONTROL_POWER_AUTO_SLEEP_TIME,
   5198                                                        (uint32 *) &
   5199                                                        sleep_time)) !=
   5200                         SOC_E_NONE) {
   5201                         sleep_time = 0;
   5202                     }
   5203                     if ((rv = bcm_port_phy_control_get(u, p,
   5204                                                        BCM_PORT_PHY_CONTROL_POWER_AUTO_WAKE_TIME,
   5205                                                        (uint32 *) &
   5206                                                        wake_time)) !=
   5207                         SOC_E_NONE) {
   5208                         wake_time = 0;
   5209                     }
   5210 
   5211                 } else if (mode_value == BCM_PORT_PHY_CONTROL_POWER_LOW) {
   5212                     str = "low";
   5213                 } else {
   5214                     str = "full";
   5215                 }
   5216             } else {
   5217                 str = "unavail";
   5218             }
   5219             /* coverity[illegal_address] */
   5220             cli_out("%5s(%3d) %16s %14s ",
   5221                     SOC_PORT_NAME(u, p), p, soc_phy_name_get(u, p), str);
   5222             if (sleep_time && wake_time) {
   5223                 cli_out("%10d %14d\n", sleep_time, wake_time);
   5224             } else {
   5225                 cli_out("%10s %14s\n", "N/A", "N/A");
   5226             }
   5227         }
   5228         return CMD_OK;
   5229     }
   5230 
   5231     if (sal_strcasecmp(mode_type, "auto_low") == 0) {
   5232         (void)_phy_auto_low_start(u, pbm, 1);
   5233     } else if (sal_strcasecmp(mode_type, "auto_off") == 0) {
   5234         (void)_phy_auto_low_start(u, pbm, 0);
   5235     } else if (sal_strcasecmp(mode_type, "low") == 0) {
   5236         DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   5237             (void)bcm_port_phy_control_set(u, p, BCM_PORT_PHY_CONTROL_POWER,
   5238                                            BCM_PORT_PHY_CONTROL_POWER_LOW);
   5239         }
   5240     } else if (sal_strcasecmp(mode_type, "full") == 0) {
   5241         DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   5242             (void)bcm_port_phy_control_set(u, p, BCM_PORT_PHY_CONTROL_POWER,
   5243                                            BCM_PORT_PHY_CONTROL_POWER_FULL);
   5244         }
   5245     } else if (sal_strcasecmp(mode_type, "auto_down") == 0) {
   5246         DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   5247             (void)bcm_port_phy_control_set(u, p, BCM_PORT_PHY_CONTROL_POWER,
   5248                                            BCM_PORT_PHY_CONTROL_POWER_AUTO);
   5249             if (sleep_time >= 0) {
   5250                 (void)bcm_port_phy_control_set(u, p,
   5251                                                BCM_PORT_PHY_CONTROL_POWER_AUTO_SLEEP_TIME,
   5252                                                sleep_time);
   5253             }
   5254             if (wake_time >= 0) {
   5255                 (void)bcm_port_phy_control_set(u, p,
   5256                                                BCM_PORT_PHY_CONTROL_POWER_AUTO_WAKE_TIME,
   5257                                                wake_time);
   5258             }
   5259         }
   5260     }
   5261 
   5262     /* free allocated memory from arg parsing */
   5263     parse_arg_eq_done(&pt);
   5264     return CMD_OK;
   5265 }
   5266 
   5267 STATIC cmd_result_t
   5268 _if_esw_phy_margin(int unit, args_t *args)
   5269 {
   5270     parse_table_t pt;
   5271     bcm_port_t port, dport;
   5272     bcm_pbmp_t pbmp;
   5273     int rv, cmd, enable;
   5274     char *cmd_str, *port_str;
   5275     int marginval = 0;
   5276 
   5277     enum { _PHY_MARGIN_MAX_GET_CMD,
   5278         _PHY_MARGIN_SET_CMD,
   5279         _PHY_MARGIN_VALUE_SET_CMD,
   5280         _PHY_MARGIN_VALUE_GET_CMD,
   5281         _PHY_MARGIN_CLEAR_CMD
   5282     };
   5283 
   5284     if ((port_str = ARG_GET(args)) == NULL) {
   5285         return CMD_USAGE;
   5286     }
   5287 
   5288     BCM_PBMP_CLEAR(pbmp);
   5289     if (parse_bcm_pbmp(unit, port_str, &pbmp) < 0) {
   5290         cli_out("Error: unrecognized port bitmap: %s\n", port_str);
   5291         return CMD_FAIL;
   5292     }
   5293 
   5294     if ((cmd_str = ARG_GET(args)) == NULL) {
   5295         return CMD_USAGE;
   5296     }
   5297     if (sal_strcasecmp(cmd_str, "maxget") == 0) {
   5298         cmd = _PHY_MARGIN_MAX_GET_CMD;
   5299         enable = 0;
   5300     } else if (sal_strcasecmp(cmd_str, "set") == 0) {
   5301         cmd = _PHY_MARGIN_SET_CMD;
   5302         enable = 1;
   5303     } else if (sal_strcasecmp(cmd_str, "valueset") == 0) {
   5304         cmd = _PHY_MARGIN_VALUE_SET_CMD;
   5305         enable = 0;
   5306     } else if (sal_strcasecmp(cmd_str, "valueget") == 0) {
   5307         cmd = _PHY_MARGIN_VALUE_GET_CMD;
   5308         enable = 0;
   5309     } else if (sal_strcasecmp(cmd_str, "clear") == 0) {
   5310         cmd = _PHY_MARGIN_CLEAR_CMD;
   5311         enable = 0;
   5312     } else
   5313         return CMD_USAGE;
   5314 
   5315     parse_table_init(unit, &pt);
   5316     if (cmd == _PHY_MARGIN_VALUE_SET_CMD) {
   5317         parse_table_add(&pt, "marginval", PQ_DFL | PQ_INT,
   5318                         (void *)(0), &marginval, NULL);
   5319     }
   5320     if (parse_arg_eq(args, &pt) < 0) {
   5321         cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   5322         parse_arg_eq_done(&pt);
   5323         return CMD_USAGE;
   5324     }
   5325 
   5326     /* Now free allocated strings */
   5327     parse_arg_eq_done(&pt);
   5328 
   5329     /* coverity[overrun-local] */
   5330     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   5331 
   5332         switch (cmd) {
   5333 
   5334             case _PHY_MARGIN_SET_CMD:
   5335             case _PHY_MARGIN_CLEAR_CMD:
   5336 
   5337                 rv = bcm_port_control_set(unit, port,
   5338                                           bcmPortControlSerdesTuneMarginMode,
   5339                                           enable);
   5340                 if (rv != BCM_E_NONE) {
   5341                     cli_out("Setting margin enable failed: %s\n",
   5342                             bcm_errmsg(rv));
   5343                     return CMD_FAIL;
   5344                 }
   5345 
   5346                 break;
   5347 
   5348             case _PHY_MARGIN_VALUE_SET_CMD:
   5349 
   5350                 rv = bcm_port_control_set(unit, port,
   5351                                           bcmPortControlSerdesTuneMarginValue,
   5352                                           marginval);
   5353                 if (rv != BCM_E_NONE) {
   5354                     cli_out("Getting margin value failed: %s\n", bcm_errmsg(rv));
   5355                     return CMD_FAIL;
   5356                 }
   5357                 cli_out("margin value(%d)\n", marginval);
   5358                 break;
   5359             case _PHY_MARGIN_MAX_GET_CMD:
   5360 
   5361                 rv = bcm_port_control_get(unit, port,
   5362                                           bcmPortControlSerdesTuneMarginMax,
   5363                                           &marginval);
   5364                 if (rv != BCM_E_NONE) {
   5365                     cli_out("Getting margin max value failed: %s\n",
   5366                             bcm_errmsg(rv));
   5367                     return CMD_FAIL;
   5368                 }
   5369                 cli_out("margin max value(%d)\n", marginval);
   5370                 break;
   5371 
   5372             case _PHY_MARGIN_VALUE_GET_CMD:
   5373 
   5374                 rv = bcm_port_control_get(unit, port,
   5375                                           bcmPortControlSerdesTuneMarginValue,
   5376                                           &marginval);
   5377                 if (rv != BCM_E_NONE) {
   5378                     cli_out("Getting margin value failed: %s\n", bcm_errmsg(rv));
   5379                     return CMD_FAIL;
   5380                 }
   5381                 cli_out("margin value(%d)\n", marginval);
   5382                 break;
   5383 
   5384             default:
   5385                 break;
   5386         }
   5387     }
   5388 
   5389     return CMD_OK;
   5390 }
   5391 
   5392 STATIC cmd_result_t
   5393 _if_esw_phy_prbs(int unit, args_t *args)
   5394 {
   5395     parse_table_t pt;
   5396     bcm_port_t port, dport;
   5397     bcm_pbmp_t pbmp;
   5398     int rv, cmd, enable, mode = 0;
   5399     char *cmd_str, *port_str, *mode_str, *poly_str = NULL;
   5400     int poly = 0, lb = 0;
   5401 
   5402     enum { _PHY_PRBS_SET_CMD, _PHY_PRBS_GET_CMD, _PHY_PRBS_CLEAR_CMD };
   5403     enum { _PHY_PRBS_SI_MODE, _PHY_PRBS_HC_MODE };
   5404 
   5405     if ((port_str = ARG_GET(args)) == NULL) {
   5406         return CMD_USAGE;
   5407     }
   5408 
   5409     BCM_PBMP_CLEAR(pbmp);
   5410     if (parse_bcm_pbmp(unit, port_str, &pbmp) < 0) {
   5411         cli_out("Error: unrecognized port bitmap: %s\n", port_str);
   5412         return CMD_FAIL;
   5413     }
   5414 
   5415     if ((cmd_str = ARG_GET(args)) == NULL) {
   5416         return CMD_USAGE;
   5417     }
   5418     if (sal_strcasecmp(cmd_str, "set") == 0) {
   5419         cmd = _PHY_PRBS_SET_CMD;
   5420         enable = 1;
   5421     } else if (sal_strcasecmp(cmd_str, "get") == 0) {
   5422         cmd = _PHY_PRBS_GET_CMD;
   5423         enable = 0;
   5424     } else if (sal_strcasecmp(cmd_str, "clear") == 0) {
   5425         cmd = _PHY_PRBS_CLEAR_CMD;
   5426         enable = 0;
   5427     } else
   5428         return CMD_USAGE;
   5429 
   5430     parse_table_init(unit, &pt);
   5431     parse_table_add(&pt, "Mode", PQ_STRING, 0, &mode_str, NULL);
   5432     if (cmd == _PHY_PRBS_SET_CMD) {
   5433             parse_table_add(&pt, "Polynomial", PQ_DFL | PQ_STRING,
   5434                         (void *)(0), &poly_str, NULL);
   5435         parse_table_add(&pt, "LoopBack", PQ_DFL | PQ_BOOL,
   5436                         (void *)(0), &lb, NULL);
   5437     }
   5438     if (parse_arg_eq(args, &pt) < 0) {
   5439         cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   5440         parse_arg_eq_done(&pt);
   5441         return CMD_USAGE;
   5442     }
   5443 
   5444     if ( poly_str ) {
   5445         if ( !sal_strcasecmp(poly_str, "P7") || !sal_strcasecmp(poly_str, "0")) {
   5446             poly = 0;
   5447         } else if (!sal_strcasecmp(poly_str, "P15") || !sal_strcasecmp(poly_str, "1")  ) {
   5448             poly = 1;
   5449         } else if (!sal_strcasecmp(poly_str, "P23") || !sal_strcasecmp(poly_str, "2") ) {
   5450             poly = 2;
   5451         } else if (!sal_strcasecmp(poly_str, "P31") || !sal_strcasecmp(poly_str, "3") ) {
   5452             poly = 3;
   5453         } else if (!sal_strcasecmp(poly_str, "P9") || !sal_strcasecmp(poly_str, "4")) {
   5454             poly = 4;
   5455         } else if (!sal_strcasecmp(poly_str, "P11") || !sal_strcasecmp(poly_str, "5") ) {
   5456             poly = 5;
   5457         } else if (!sal_strcasecmp(poly_str, "P58") || !sal_strcasecmp(poly_str, "6")) {
   5458             poly = 6;
   5459         }else {
   5460             cli_out("Prbs p must be P7(0), P15(1), P23(2), P31(3), P9(4), P11(5), or P58(6).\n");
   5461             parse_arg_eq_done(&pt);
   5462             return CMD_FAIL;
   5463         }
   5464     }
   5465 
   5466     if (mode_str) {
   5467         if (sal_strcasecmp(mode_str, "si") == 0) {
   5468             mode = 1;
   5469         } else if (sal_strcasecmp(mode_str, "hc") == 0) {
   5470             mode = 0;
   5471         } else {
   5472                 cli_out("Prbs mode must be si, mac, phy or hc.\n");
   5473                 parse_arg_eq_done(&pt);
   5474                 return CMD_FAIL;
   5475         }
   5476     }
   5477 
   5478     /* Now free allocated strings */
   5479     parse_arg_eq_done(&pt);
   5480 
   5481     /* coverity[overrun-local] */
   5482     DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   5483 
   5484             /* First set prbs mode */
   5485             rv = bcm_port_control_set(unit, port, bcmPortControlPrbsMode, mode);
   5486             if (rv != BCM_E_NONE) {
   5487                 cli_out("Setting prbs mode failed: %s\n", bcm_errmsg(rv));
   5488                 return CMD_FAIL;
   5489             }
   5490         if (cmd == _PHY_PRBS_SET_CMD || cmd == _PHY_PRBS_CLEAR_CMD) {
   5491             if (poly >= 0 && poly <= 6) {
   5492                 /* Set polynomial */
   5493                 rv = bcm_port_control_set(unit, port,
   5494                                           bcmPortControlPrbsPolynomial, poly);
   5495                 if (rv != BCM_E_NONE) {
   5496                     cli_out("Setting prbs polynomial failed: %s\n",
   5497                             bcm_errmsg(rv));
   5498                     return CMD_FAIL;
   5499                 }
   5500             } else {
   5501                 cli_out("Polynomial must be 0..6.\n");
   5502                 return CMD_FAIL;
   5503             }
   5504 
   5505             /* 
   5506              * Set tx/rx enable. If clear, enable == 0
   5507              * Note that the order of enabling is important. The following
   5508              * steps are listed in the SI Block description in the uArch Spec.
   5509              * - Disable the normal receive path at the receive end. This is done
   5510              *     via SI_CONFIG0.enable;
   5511              * - Enable the PRBS generator at the transmit end,
   5512              *     SI_CONFIG0.prbs_generator_en;
   5513              * - Allow enough time for the PRBS stream to be received at the
   5514              *     monitor end
   5515              * - Enable the PRBS monitor, SI_CONFIG0.prbs_monitor_en
   5516              * - Read the PRBS error register to clear the error counter
   5517              */
   5518             if (lb) {
   5519                 enable |= 0x8000;
   5520             }
   5521             rv = bcm_port_control_set(unit, port,
   5522                                       bcmPortControlPrbsTxEnable, enable);
   5523             if (rv != BCM_E_NONE) {
   5524                 cli_out("Setting prbs tx enable failed: %s\n", bcm_errmsg(rv));
   5525                 return CMD_FAIL;
   5526             }
   5527 
   5528             rv = bcm_port_control_set(unit, port,
   5529                                       bcmPortControlPrbsRxEnable, enable);
   5530             if (rv != BCM_E_NONE) {
   5531                 cli_out("Setting prbs rx enable failed: %s\n", bcm_errmsg(rv));
   5532                 return CMD_FAIL;
   5533             }
   5534         } else {                /* _PHY_PRBS_GET_CMD */
   5535             int status;
   5536 
   5537             /*If reading twice the error count will be missed.*/
   5538             rv = bcm_port_control_get(unit, port,
   5539                                       bcmPortControlPrbsRxStatus, &status);
   5540             if (rv != BCM_E_NONE) {
   5541                 cli_out("Getting prbs rx status failed: %s\n",
   5542                         bcm_errmsg(rv));
   5543                 return CMD_FAIL;
   5544             }
   5545 
   5546             switch (status) {
   5547                 case 0:
   5548                     cli_out("%s (%2d):  PRBS OK!\n", BCM_PORT_NAME(unit, port),
   5549                             port);
   5550                     break;
   5551                 case -1:
   5552                     cli_out("%s (%2d):  PRBS Failed!\n",
   5553                             BCM_PORT_NAME(unit, port), port);
   5554                     break;
   5555                 default:
   5556                     cli_out("%s (%2d):  PRBS has %d errors!\n",
   5557                             BCM_PORT_NAME(unit, port), port, status);
   5558                     break;
   5559             }
   5560         }
   5561     }
   5562     return CMD_OK;
   5563 }
   5564 
   5565 #ifdef BCM_TOMAHAWK3_SUPPORT
   5566 /* PRBSStat is a command to periodically collect PRBS error counters and 
   5567  * compute BER based on the port configuration and the observed errorr 
   5568  * counters. The command processes and displays counters and BER calculation 
   5569  * for all lanes on a given port. 
   5570 */
   5571 
   5572 #define PRBS_STAT_F_INIT        (1 << 0)
   5573 #define PRBS_STAT_F_RUNNING     (1 << 1)
   5574 
   5575 #define PRBS_STAT_INIT(f)       (f & PRBS_STAT_F_INIT)
   5576 #define PRBS_STAT_RUNNING(f)    (f & PRBS_STAT_F_RUNNING)
   5577 
   5578 #define PM_MAX_LANES          8
   5579 
   5580 #define PRBS_STAT_LOCK(lock)      \
   5581     if (lock) { \
   5582         sal_mutex_take(lock, sal_mutex_FOREVER);   \
   5583     }
   5584 
   5585 #define PRBS_STAT_UNLOCK(lock) \
   5586     if (lock) { \
   5587         sal_mutex_give(lock); \
   5588     }
   5589 
   5590 typedef struct prbs_stat_subcounter_s {
   5591     uint64 errors;      /* PRBS errors */
   5592     uint64 losslock;    /* Loss of lock */
   5593 } prbs_stat_subcounter_t;
   5594 
   5595 /*
   5596  * Callback function -
   5597  */
   5598 typedef void (*prbs_stat_handler_func_t)(int unit, bcm_port_t port,
   5599                                          int lane, uint32 errors,
   5600                                          int losslock);
   5601 int
   5602 prbs_stat_ber_get(int unit, bcm_port_t port, int lane, double *ber,
   5603                   int *interval);
   5604 int
   5605 prbs_stat_handler_register(int unit, prbs_stat_handler_func_t func);
   5606 
   5607 int
   5608 prbs_stat_handler_unregister(int unit, prbs_stat_handler_func_t func);
   5609 
   5610 /*
   5611  * Acc: accummulated from beginning/last clear
   5612  * Cur: count since last time shown
   5613  */
   5614 typedef struct prbs_stat_counter_s {
   5615     prbs_stat_subcounter_t acc;
   5616     prbs_stat_subcounter_t cur;
   5617 } prbs_stat_counter_t;
   5618 
   5619 /*
   5620  * Per port info
   5621  */
   5622 typedef struct prbs_stat_pinfo_s {
   5623     int speed;
   5624     int lanes;
   5625     bcm_port_phy_fec_t fec_type;
   5626     int intervals[PM_MAX_LANES];   /* Intervals expired since last show */
   5627     int prbs_lock[PM_MAX_LANES];
   5628     prbs_stat_counter_t counters[PM_MAX_LANES]; /* Counters per port/lane */
   5629     double ber[PM_MAX_LANES]; /* BER updated every interval */
   5630 } prbs_stat_pinfo_t;
   5631 
   5632 typedef struct prbs_stat_handler_s {
   5633     struct prbs_stat_handler_s *next;
   5634     prbs_stat_handler_func_t func;
   5635 } prbs_stat_handler_t;
   5636 
   5637 
   5638 /*
   5639  * The main control block
   5640  *
   5641  * The hardware polling interval is stored in secs. Due to the latched
   5642  * clear-on-read hardware register behavior, the interval determines
   5643  * how fast new data is available to be examined with show counters / show
   5644  * ber. If show commands are called before an interval has transpired,
   5645  * there will be no new errors or ber computation available.
   5646  *
   5647  * Loss of lock events are recorded. For counters, there are lossoflock
   5648  * counters that get displayed. For BER computation, once there is a
   5649  * loss of lock, the BER computation will not be updated until the
   5650  * next show ber is called. This ensures loss of lock events are
   5651  * noticed in the show ber output.
   5652  */
   5653 typedef struct prbs_stat_cb_ {
   5654     uint32 flags;
   5655     int secs;
   5656     bcm_pbmp_t pbmp;
   5657     prbs_stat_pinfo_t pinfo[BCM_PBMP_PORT_MAX];
   5658     sal_sem_t sem;
   5659     sal_thread_t thread_id;
   5660     sal_mutex_t lock;
   5661     sal_mutex_t handler_lock;
   5662     prbs_stat_handler_t *handlers;      /* Registered callback list */
   5663 } prbs_stat_cb_t;
   5664 
   5665 /* Lookup table to determine VCO, base rate */
   5666 typedef struct stat_speed_entry_ {
   5667     uint32 speed;               /* port speed in Mbps */
   5668     uint32 num_lanes;           /* number of lanes */
   5669     bcm_port_phy_fec_t fec_type; /* FEC type */
   5670     int vco;                    /* associated VCO rate of the ability */
   5671     double rate;                /* base rate for speed */
   5672 } stat_speed_entry_t;
   5673 
   5674 /* List of speed, lane, fec, VCO, and rate */
   5675 stat_speed_entry_t stat_speed_table[] =
   5676 {
   5677     /* speed  lane fec_type             vco base rate(Gbps) */
   5678     {10000,     1, bcmPortPhyFecNone,   20, 10.3125},
   5679     {10000,     1, bcmPortPhyFecBaseR,  20, 10.3125},
   5680     {20000,     1, bcmPortPhyFecNone,   20, 10.3125},
   5681     {20000,     1, bcmPortPhyFecBaseR,  20, 10.3125},
   5682     {40000,     4, bcmPortPhyFecNone,   20, 10.3125},
   5683     {40000,     4, bcmPortPhyFecBaseR,  20, 10.3125},
   5684     {40000,     2, bcmPortPhyFecNone,   20, 10.3125},
   5685     {25000,     1, bcmPortPhyFecNone,   25, 25.78125},
   5686     {25000,     1, bcmPortPhyFecBaseR,  25, 25.78125},
   5687     {25000,     1, bcmPortPhyFecRsFec,  25, 25.7812},
   5688     {50000,     1, bcmPortPhyFecNone,   25, 51.5625},
   5689     {50000,     1, bcmPortPhyFecRsFec,  25, 51.5625},
   5690     {50000,     1, bcmPortPhyFecRs544,  26, 53.125},
   5691     {50000,     1, bcmPortPhyFecRs272,  26, 53.125},
   5692     {50000,     2, bcmPortPhyFecNone,   25, 25.78125},
   5693     {50000,     2, bcmPortPhyFecRsFec,  25, 25.78125},
   5694     {50000,     2, bcmPortPhyFecRs544,  26, 26.5625},
   5695     {100000,    2, bcmPortPhyFecNone,   25, 51.5625},
   5696     {100000,    2, bcmPortPhyFecRsFec,  25, 51.5625},
   5697     {100000,    2, bcmPortPhyFecRs544,  26, 53.125},
   5698     {100000,    2, bcmPortPhyFecRs272,  26, 53.125},
   5699     {100000,    4, bcmPortPhyFecNone,   25, 25.78125},
   5700     {100000,    4, bcmPortPhyFecRsFec,  25, 25.78125},
   5701     {100000,    4, bcmPortPhyFecRs544,  26, 26.5625},
   5702     {200000,    4, bcmPortPhyFecNone,   25, 51.5625},
   5703     {200000,    4, bcmPortPhyFecRs272,  26, 53.125},
   5704     {200000,    4, bcmPortPhyFecRs544,  26, 53.125},
   5705     {200000,    4, bcmPortPhyFecRs544_2xN,  26, 53.125},
   5706     {400000,    8, bcmPortPhyFecRs544_2xN,  26, 53.125}
   5707 };
   5708 
   5709 prbs_stat_cb_t prbs_stat_cb[BCM_MAX_NUM_UNITS];
   5710 
   5711 /*
   5712  * Get base rate in Gbps for port based on port speed, lanes, and FEC
   5713  */
   5714 STATIC int
   5715 stat_speed_rate_get(int speed, int num_lanes, bcm_port_phy_fec_t fec_type,
   5716                     double *rate)
   5717 {
   5718     int i;
   5719     int entries;
   5720 
   5721     *rate = 0.;
   5722     entries = sizeof(stat_speed_table) / sizeof(stat_speed_entry_t);
   5723     for (i = 0; i < entries; i++) {
   5724         if (stat_speed_table[i].speed == speed &&
   5725             stat_speed_table[i].num_lanes == num_lanes &&
   5726             stat_speed_table[i].fec_type == fec_type)
   5727         {
   5728             *rate = stat_speed_table[i].rate;
   5729             break;
   5730         }
   5731     }
   5732     return BCM_E_NONE;
   5733 }
   5734 
   5735 STATIC int
   5736 prbs_stat_ber_compute(int unit, bcm_port_t port, int lanes,
   5737                       uint32 delta, sal_time_t secs,
   5738                       double *ber)
   5739 {
   5740     double rate;
   5741     double nbits;
   5742     prbs_stat_pinfo_t *psp;
   5743 
   5744     if (secs < 1) {
   5745         return 0;
   5746     }
   5747 
   5748     /* Make sure BER is computed at max if no errors */
   5749     if ( delta == 0){
   5750         delta = 1;
   5751     }
   5752     psp = &(prbs_stat_cb[unit].pinfo[port]);
   5753     stat_speed_rate_get(psp->speed, psp->lanes, psp->fec_type, &rate);
   5754 
   5755     /* Rate needs to be adjusted from Gbps to bps */
   5756     rate = rate * 1024. * 1024. * 1024.;
   5757     nbits = rate * lanes;
   5758     *ber = delta / (nbits * secs);
   5759 
   5760     return 1;
   5761 }
   5762 
   5763 STATIC void
   5764 prbs_stat_handler_notify(int unit, bcm_port_t port, int lane, uint32 errors,
   5765                          int losslock)
   5766 {
   5767     prbs_stat_cb_t *pscb;
   5768     prbs_stat_handler_t *h, *next;
   5769 
   5770     pscb = &(prbs_stat_cb[unit]);
   5771     /* Notify all registered callbacks */
   5772     PRBS_STAT_LOCK(pscb->handler_lock);
   5773     for (h = pscb->handlers; h != NULL; h = next) {
   5774         next = h->next;
   5775         h->func(unit, port, lane, errors, losslock);
   5776     }
   5777     PRBS_STAT_UNLOCK(pscb->handler_lock);
   5778 }
   5779 
   5780 STATIC void
   5781 prbs_stat_counter_show(char *cname, char *pname, int lane,
   5782                        uint64 acc_counter, uint64 cur_counter,
   5783                        sal_time_t secs, int show_rate)
   5784 {
   5785     char chdr[32];
   5786     char buf[64];
   5787     uint64 delta;
   5788 
   5789     sal_sprintf(chdr, "%s.%s[%d]", cname, pname, lane);
   5790     COMPILER_64_COPY(delta, acc_counter);
   5791     COMPILER_64_SUB_64(delta, cur_counter);
   5792     if (!COMPILER_64_IS_ZERO(delta)) {
   5793         /* Show couters since beginning */
   5794         format_uint64_decimal(buf, acc_counter, ',');
   5795         LOG_CLI(("%-20s: %20s", chdr, buf));
   5796 
   5797         /* Show counters since last show */
   5798         format_uint64_decimal(buf, delta, ',');
   5799         LOG_CLI(("  %20s",buf));
   5800 
   5801         if (show_rate) {
   5802             /* Show counters per second */
   5803             COMPILER_64_UDIV_32(delta, (uint32)secs);
   5804             format_uint64_decimal(buf, delta, ',');
   5805             LOG_CLI(("  %12s/s",buf));
   5806         }
   5807         LOG_CLI(("\n"));
   5808     }
   5809 }
   5810 
   5811 
   5812 STATIC int
   5813 prbs_stat_port_counter(int unit, bcm_port_t port)
   5814 {
   5815     int lane;
   5816     int unlocked = 0;
   5817     prbs_stat_cb_t *pscb;
   5818     prbs_stat_pinfo_t *pspi;
   5819     prbs_stat_counter_t *psco;
   5820 
   5821     pscb = &(prbs_stat_cb[unit]);
   5822     pspi = &(pscb->pinfo[port]);
   5823     psco = pspi->counters;
   5824 
   5825     for (lane = 0; lane < pspi->lanes; lane++) {
   5826         if (!pspi->prbs_lock[lane]) {
   5827             unlocked++;
   5828         }
   5829     }
   5830     if (unlocked == pspi->lanes) {
   5831         LOG_CLI(("%s: no PRBS lock\n", BCM_PORT_NAME(unit, port)));
   5832     }
   5833 
   5834     for (lane = 0; lane < pspi->lanes; lane++) {
   5835         prbs_stat_counter_show("ERRORS", BCM_PORT_NAME(unit, port),
   5836                                lane, psco[lane].acc.errors,
   5837                                psco[lane].cur.errors,
   5838                                pscb->secs * pspi->intervals[lane], TRUE);
   5839         pspi->intervals[lane] = 0;
   5840         psco[lane].cur.errors = psco[lane].acc.errors;
   5841     }
   5842 
   5843     for (lane = 0; lane < pspi->lanes; lane++) {
   5844         prbs_stat_counter_show("LOSSLOCK", BCM_PORT_NAME(unit, port),
   5845                                lane, psco[lane].acc.losslock,
   5846                                psco[lane].cur.losslock, 0, FALSE);
   5847         psco[lane].cur.losslock = psco[lane].acc.losslock;
   5848     }
   5849 
   5850 
   5851     return 1;
   5852 }
   5853 
   5854 STATIC void
   5855 prbs_stat_ber_update(int unit, bcm_port_t port, int lane, uint32 delta)
   5856 {
   5857     double ber;
   5858     prbs_stat_cb_t *pscb;
   5859     prbs_stat_pinfo_t *pspi;
   5860 
   5861     pscb = &(prbs_stat_cb[unit]);
   5862     pspi = &(pscb->pinfo[port]);
   5863 
   5864     if (delta >= 0) {
   5865         if (!prbs_stat_ber_compute(unit, port, 1, delta, pscb->secs, &ber)) {
   5866             LOG_ERROR(BSL_LS_APPL_PHY,
   5867                       (BSL_META_U(unit,
   5868                                   "%s[%d]: could not compute BER\n"),
   5869                                   BCM_PORT_NAME(unit, port), lane));
   5870             return;
   5871         }
   5872         pspi->ber[lane] = ber;
   5873         LOG_DEBUG(BSL_LS_APPL_PHY,
   5874                   (BSL_META_U(unit, "Updated BER for port %d: %8.2e (delta=%d)\n"),
   5875                    port, ber, delta));
   5876     } else {
   5877         pspi->ber[lane] = 0;
   5878     }
   5879 }
   5880 
   5881 /*
   5882  * If there is a port configuration change, update the new configuration
   5883  * and clear counters, BER
   5884  */
   5885 STATIC int
   5886 prbs_stat_pinfo_update(int unit, bcm_port_t port)
   5887 {
   5888     prbs_stat_pinfo_t *pspi;
   5889     prbs_stat_counter_t *psco;
   5890     bcm_port_resource_t rsrc;
   5891 
   5892     pspi = &(prbs_stat_cb[unit].pinfo[port]);
   5893 
   5894     BCM_IF_ERROR_RETURN(bcm_port_resource_speed_get(unit, port, &rsrc));
   5895     if ((pspi->speed == rsrc.speed) &&
   5896         (pspi->lanes == rsrc.lanes) &&
   5897         (pspi->fec_type == rsrc.fec_type)) {
   5898         return 1;
   5899     }
   5900 
   5901     LOG_DEBUG(BSL_LS_APPL_PHY,
   5902               (BSL_META_U(unit, "Updating %s config\n"),
   5903                BCM_PORT_NAME(unit, port)));
   5904 
   5905     PRBS_STAT_LOCK(prbs_stat_cb[unit].lock);
   5906     pspi->speed = rsrc.speed;
   5907     pspi->lanes = rsrc.lanes;
   5908     pspi->fec_type = rsrc.fec_type;
   5909 
   5910     psco = pspi->counters;
   5911     sal_memset(psco, 0, sizeof(prbs_stat_counter_t) * PM_MAX_LANES);
   5912     sal_memset(&(pspi->ber), 0, sizeof(double) * PM_MAX_LANES);
   5913     PRBS_STAT_UNLOCK(prbs_stat_cb[unit].lock);
   5914 
   5915     return 1;
   5916 }
   5917 
   5918 
   5919 STATIC int
   5920 prbs_stat_collect(int unit, bcm_port_t port)
   5921 {
   5922     int rv;
   5923     int lane;
   5924     uint32 status;
   5925     uint64 lcount;
   5926     bcm_gport_t gport;
   5927     prbs_stat_pinfo_t *pspi;
   5928     prbs_stat_counter_t *psco;
   5929 
   5930     prbs_stat_pinfo_update(unit, port);
   5931     pspi = &(prbs_stat_cb[unit].pinfo[port]);
   5932     psco = pspi->counters;
   5933 
   5934     PRBS_STAT_LOCK(prbs_stat_cb[unit].lock);
   5935     for (lane = 0; lane < pspi->lanes; lane++) {
   5936         COMPILER_64_SET(lcount, 0, 0);
   5937         BCM_PHY_GPORT_LANE_PORT_SET(gport, lane, port);
   5938         rv = bcm_port_phy_control_get(0, gport,
   5939                                       BCM_PORT_PHY_CONTROL_PRBS_RX_STATUS,
   5940                                       &status);
   5941         if (BCM_FAILURE(rv)) {
   5942             PRBS_STAT_UNLOCK(prbs_stat_cb[unit].lock);
   5943             return 0;
   5944         }
   5945         LOG_DEBUG(BSL_LS_APPL_PHY,
   5946                   (BSL_META_U(unit, "%s: collecting status %d\n"),
   5947                    BCM_PORT_NAME(unit, port), status));
   5948 
   5949         switch (status) {
   5950         case -1:
   5951             pspi->prbs_lock[lane] = 0;
   5952             pspi->ber[lane] = 0;
   5953             break;
   5954         case -2:
   5955             pspi->prbs_lock[lane] = 1;
   5956             COMPILER_64_ADD_32(psco[lane].acc.losslock, 1);
   5957             pspi->ber[lane] = -2;
   5958             prbs_stat_handler_notify(unit, port, lane, 0, 1);
   5959             break;
   5960         default:
   5961             pspi->prbs_lock[lane] = 1;
   5962             COMPILER_64_SET(lcount, 0, status);
   5963             COMPILER_64_ADD_64(psco[lane].acc.errors, lcount);
   5964             pspi->intervals[lane]++;
   5965             if (pspi->ber[lane] != -2) {
   5966                 /*
   5967                  * Do not update BER to preserve the loss of lock event.
   5968                  * The next show BER will 'unlatch' the loss of lock event
   5969                  * and restart BER calculation. Without this, the loss
   5970                  * of lock event will be lost if multiple intervals
   5971                  * transpire between show ber calls.
   5972                  */
   5973                 prbs_stat_ber_update(unit, port, lane, status);
   5974             }
   5975             prbs_stat_handler_notify(unit, port, lane, status, 0);
   5976         }
   5977     }
   5978     PRBS_STAT_UNLOCK(prbs_stat_cb[unit].lock);
   5979 
   5980     return 1;
   5981 }
   5982 
   5983 STATIC void
   5984 prbs_stat_thread(int unit)
   5985 {
   5986     int u_interval;
   5987     bcm_port_t port;
   5988     prbs_stat_cb_t *pscb;
   5989 
   5990     pscb = &(prbs_stat_cb[unit]);
   5991     u_interval = pscb->secs * 1000000; /* Adjust to usec */
   5992 
   5993     while (pscb->secs) {
   5994         BCM_PBMP_ITER(pscb->pbmp, port) {
   5995             LOG_DEBUG(BSL_LS_APPL_PHY,
   5996                       (BSL_META_U(unit, "Collecting PRBS for port %d\n"), port));
   5997             if (!prbs_stat_collect(unit, port)) {
   5998                 LOG_ERROR(BSL_LS_APPL_PHY,
   5999                           (BSL_META_U(
   6000                               unit,
   6001                               "Failed collecting PRBS stats for port %d\n"), port));
   6002             }
   6003         }
   6004         sal_sem_take(pscb->sem, u_interval);
   6005     }
   6006 
   6007     PRBS_STAT_LOCK(pscb->lock);
   6008     BCM_PBMP_ITER(pscb->pbmp, port) {
   6009         sal_memset(&(prbs_stat_cb[unit].pinfo[port].counters),
   6010                    0, sizeof(prbs_stat_counter_t) * PM_MAX_LANES);
   6011     }
   6012     pscb->flags &= ~PRBS_STAT_F_RUNNING;
   6013     PRBS_STAT_UNLOCK(pscb->lock);
   6014 
   6015     pscb->thread_id = NULL;
   6016     LOG_DEBUG(BSL_LS_APPL_PHY, ("PRBS stat thread exiting...\n"));
   6017     sal_thread_exit(0);
   6018 }
   6019 
   6020 
   6021 STATIC int
   6022 prbs_stat_init(int unit)
   6023 {
   6024     prbs_stat_cb_t *pscb;
   6025 
   6026     pscb = &(prbs_stat_cb[unit]);
   6027     if (PRBS_STAT_INIT(pscb->flags)) {
   6028         return 1;
   6029     }
   6030     sal_memset(pscb, 0, sizeof(prbs_stat_cb_t));
   6031     pscb->flags = PRBS_STAT_F_INIT;
   6032     pscb->handlers = NULL;
   6033     if ((pscb->lock = sal_mutex_create("PRBSStat lock")) == NULL)
   6034         return 0;
   6035     if ((pscb->handler_lock = sal_mutex_create("PRBSStat handler lock")) == NULL)
   6036         return 0;
   6037     if ((pscb->sem = sal_sem_create("PRBSStat sleep", sal_sem_BINARY, 0)) == NULL)
   6038         return 0;
   6039 
   6040     return 1;
   6041 }
   6042 
   6043 STATIC int
   6044 prbs_stat_clear(int unit, bcm_pbmp_t pbmp, args_t *a)
   6045 {
   6046     bcm_port_t port;
   6047 /*
   6048     bcm_pbmp_t pbmp;
   6049 
   6050     if (!prbs_stat_pbmp_parse(unit, a, &pbmp)) {
   6051         return CMD_USAGE;
   6052     }
   6053 */
   6054     PRBS_STAT_LOCK(prbs_stat_cb[unit].lock);
   6055     BCM_PBMP_ITER(pbmp, port) {
   6056         sal_memset(&(prbs_stat_cb[unit].pinfo[port].counters),
   6057                    0, sizeof(prbs_stat_counter_t) * PM_MAX_LANES);
   6058     }
   6059     PRBS_STAT_UNLOCK(prbs_stat_cb[unit].lock);
   6060     return CMD_OK;
   6061 }
   6062 
   6063 
   6064 STATIC int
   6065 prbs_stat_counter(int unit, bcm_pbmp_t pbmp, args_t *a)
   6066 {
   6067     int rv = 1;
   6068     bcm_port_t port;
   6069 /*
   6070     bcm_pbmp_t pbmp;
   6071 
   6072     if (!prbs_stat_pbmp_parse(unit, a, &pbmp)) {
   6073         return CMD_USAGE;
   6074     }
   6075 */
   6076     if (!PRBS_STAT_RUNNING(prbs_stat_cb[unit].flags)) {
   6077         LOG_CLI(("PRBSStat not running\n"));
   6078         return CMD_FAIL;
   6079     }
   6080 
   6081     PRBS_STAT_LOCK(prbs_stat_cb[unit].lock);
   6082     LOG_CLI(("%-20s  %20s  %20s  %12s", 
   6083         "port", "accumulated count", "last count", "count per sec\n"));
   6084     BCM_PBMP_ITER(pbmp, port) {
   6085         rv = prbs_stat_port_counter(unit, port);
   6086         if (!rv) {
   6087             break;
   6088         }
   6089     }
   6090 
   6091     PRBS_STAT_UNLOCK(prbs_stat_cb[unit].lock);
   6092     return rv ? CMD_OK : CMD_FAIL;
   6093 }
   6094 
   6095 
   6096 STATIC int
   6097 prbs_stat_ber(int unit,  bcm_pbmp_t pbmp, args_t *a)
   6098 {
   6099     int lane;
   6100     bcm_port_t port;
   6101 /*
   6102     bcm_pbmp_t pbmp;
   6103 */
   6104     prbs_stat_cb_t *pscb;
   6105     prbs_stat_pinfo_t *pspi;
   6106 
   6107 /*
   6108     if (!prbs_stat_pbmp_parse(unit, a, &pbmp)) {
   6109         return CMD_USAGE;
   6110     }
   6111 */
   6112 
   6113     pscb = &(prbs_stat_cb[unit]);
   6114     if (!PRBS_STAT_RUNNING(pscb->flags)) {
   6115         LOG_CLI(("PRBSStat not running\n"));
   6116         return CMD_FAIL;
   6117     }
   6118 
   6119     LOG_CLI(("%-6s   %s", "port", "BER\n"));
   6120     LOG_CLI(("====\n"));
   6121     PRBS_STAT_LOCK(pscb->lock);
   6122     BCM_PBMP_ITER(pbmp, port) {
   6123         pspi = &(pscb->pinfo[port]);
   6124         for (lane = 0; lane < pspi->lanes; lane++) {
   6125             if (pspi->ber[lane] == -2) {
   6126                 LOG_CLI(("%s[%d] : LossOfLock\n", BCM_PORT_NAME(unit, port), lane));
   6127                 pspi->ber[lane] = 0;    /* Clear it here now that has been displayed */
   6128             } else if (pspi->ber[lane]) {
   6129                 LOG_CLI(("%s[%d] : %4.2e\n", BCM_PORT_NAME(unit, port),
   6130                          lane, pspi->ber[lane]));
   6131             } else {
   6132                 LOG_CLI(("%s[%d] : NoLock\n", BCM_PORT_NAME(unit, port), lane));
   6133             }
   6134         }
   6135         LOG_CLI(("====\n"));
   6136     }
   6137     PRBS_STAT_UNLOCK(pscb->lock);
   6138     return CMD_OK;
   6139 }
   6140 
   6141 
   6142 STATIC int
   6143 prbs_stat_stop(int unit)
   6144 {
   6145     prbs_stat_cb_t *pscb;
   6146 
   6147     pscb = &(prbs_stat_cb[unit]);
   6148     if (PRBS_STAT_RUNNING(pscb->flags)) {
   6149         /* Signal thread to stop running */
   6150         pscb->secs = 0;
   6151         LOG_CLI(("Stopping PRBSStat thread\n"));
   6152         sal_sem_give(pscb->sem);
   6153         /* Cleared when thread exit -- pscb->flags &= ~PRBS_STAT_F_RUNNING; */
   6154     } else {
   6155         LOG_CLI(("PRBSStat already stopped\n"));
   6156     }
   6157 
   6158     return CMD_OK;
   6159 }
   6160 
   6161 
   6162 STATIC void
   6163 prbs_stat_counter_init(int unit)/*, bcm_pbmp_t pbmp)*/
   6164 {
   6165     int lane;
   6166     uint32 status;
   6167     bcm_port_t port;
   6168     bcm_gport_t gport;
   6169     prbs_stat_cb_t *pscb;
   6170     prbs_stat_pinfo_t *pspi;
   6171     prbs_stat_counter_t *psco;
   6172 
   6173     pscb = &(prbs_stat_cb[unit]);
   6174 
   6175     BCM_PBMP_ITER(pscb->pbmp, port) {
   6176         pspi = &(pscb->pinfo[port]);
   6177         psco = pspi->counters;
   6178 
   6179         sal_memset(psco, 0,sizeof(prbs_stat_counter_t) * PM_MAX_LANES);
   6180         sal_memset(&(pspi->ber), 0, sizeof(double) * PM_MAX_LANES);
   6181 
   6182         /* Prime PRBS once to clear hardware counters */
   6183         for (lane = 0; lane < pspi->lanes; lane++) {
   6184             BCM_PHY_GPORT_LANE_PORT_SET(gport, lane, port);
   6185             bcm_port_phy_control_get(unit, gport,
   6186                                      BCM_PORT_PHY_CONTROL_PRBS_RX_STATUS,
   6187                                      &status);
   6188             pspi->intervals[lane] = 0;
   6189         }
   6190     }
   6191 }
   6192 
   6193 STATIC int
   6194 prbs_stat_start(int unit, bcm_pbmp_t pbmp, args_t *a)
   6195 {
   6196     int secs;
   6197     /*bcm_pbmp_t pbmp;*/
   6198     parse_table_t   pt;
   6199     prbs_stat_cb_t *pscb;
   6200 
   6201     pscb = &(prbs_stat_cb[unit]);
   6202 
   6203     if (ARG_CNT(a) == 0) {
   6204         if (!(pscb->flags & PRBS_STAT_F_RUNNING)) {
   6205             LOG_CLI(("PRBSStat: not running\n"));
   6206         } else {
   6207             char pbmp_str[SOC_PBMP_FMT_LEN];
   6208             SOC_PBMP_FMT(pscb->pbmp, pbmp_str);
   6209             LOG_CLI(("PRBSStat: interval=%ds\n", pscb->secs));
   6210             LOG_CLI(("PRBSStat: pbmp=%s\n", pbmp_str));
   6211         }
   6212         return CMD_OK;
   6213     }
   6214 
   6215     /*BCM_PBMP_ASSIGN(pbmp, pscb->pbmp);*/
   6216     secs = pscb->secs;
   6217 
   6218     parse_table_init(unit, &pt);
   6219     parse_table_add(&pt, "Interval", PQ_DFL|PQ_INT, 0, &secs, NULL);
   6220     /*parse_table_add(&pt, "PortBitMap",PQ_DFL|PQ_PBMP, 0, &pbmp, NULL);*/
   6221 
   6222     if (parse_arg_eq(a, &pt) < 0) {
   6223         cli_out("%s: Error: Unknown option: %s\n", ARG_CMD(a), ARG_CUR(a));
   6224         parse_arg_eq_done(&pt);
   6225         return CMD_USAGE;
   6226     }
   6227     parse_arg_eq_done(&pt);
   6228 
   6229     if (secs == 0 || secs > 180) {
   6230         LOG_CLI(("Interval must be between 1 and 180 seconds\n"));
   6231         return CMD_USAGE;
   6232     }
   6233 
   6234     /*
   6235      * Allow start to be called while already running to update
   6236      * interval and pbmp
   6237      */
   6238     if (pscb->flags & PRBS_STAT_F_RUNNING) {
   6239         PRBS_STAT_LOCK(pscb->lock);
   6240     }
   6241 
   6242     pscb->secs = secs;
   6243     BCM_PBMP_ASSIGN(pscb->pbmp, pbmp);
   6244 
   6245     prbs_stat_counter_init(unit);
   6246 
   6247     if (pscb->flags & PRBS_STAT_F_RUNNING) {
   6248         PRBS_STAT_UNLOCK(pscb->lock);
   6249         /* Must return without starting new thread */
   6250         return CMD_OK;
   6251     }
   6252 
   6253     /* Thread should not be running */
   6254     if (pscb->thread_id != NULL) {
   6255         LOG_CLI(("PRBSStat thread already running\n"));
   6256         return CMD_FAIL;
   6257     }
   6258 
   6259     pscb->thread_id = sal_thread_create("PRBSstat",
   6260                                       SAL_THREAD_STKSZ,
   6261                                       100,   /* thread priority */
   6262                                       (void (*)(void*))prbs_stat_thread,
   6263                                       INT_TO_PTR(unit));
   6264     if (pscb->thread_id == SAL_THREAD_ERROR) {
   6265         LOG_ERROR(BSL_LS_APPL_PHY,
   6266             (BSL_META_U(unit, "Could not create PRBSstat thread\n")));
   6267         pscb->flags &= ~PRBS_STAT_F_RUNNING;
   6268         return CMD_FAIL;
   6269     }
   6270     LOG_CLI(("PRBSStat thread started...\n"));
   6271     pscb->flags |= PRBS_STAT_F_RUNNING;
   6272 
   6273     return CMD_OK;
   6274 }
   6275 
   6276 
   6277 /*
   6278  * Callback testing
   6279  */
   6280 
   6281 STATIC void
   6282 prbs_stat_test_callback(int unit, bcm_port_t port, int lane, uint32 errors, int losslock)
   6283 {
   6284     if (losslock) {
   6285         LOG_CLI(("%s[%d]: locklock=%d\n", BCM_PORT_NAME(unit, port),
   6286                  lane, losslock));
   6287     } else if (errors) {
   6288         LOG_CLI(("%s[%d]: errors=%-8d\n", BCM_PORT_NAME(unit, port),
   6289                  lane, errors));
   6290     }
   6291 }
   6292 
   6293 
   6294 /*
   6295  * Match input with key. Allows abbreviated matches based on
   6296  * the minimum initial capital letters in key. For example,
   6297  * key = ABCdef will be matched with the input
   6298  * abc, abcd, abcde, abcdef. Any other input is a mismatch.
   6299  */
   6300 STATIC int
   6301 prbs_stat_cmd_match(char *inp, char *key)
   6302 {
   6303     while (*key && isupper(*key)) {
   6304         if (!*inp || (toupper(*inp) != *key)) {
   6305             return 0;
   6306         }
   6307         key++;
   6308         inp++;
   6309     }
   6310     while (*inp) {
   6311         if (toupper(*inp) != toupper(*key)) {
   6312             return 0;
   6313         }
   6314         key++;
   6315         inp++;
   6316     }
   6317     return 1;
   6318 }
   6319 
   6320 
   6321 STATIC int
   6322 prbs_stat_callback_test(int unit, args_t *a)
   6323 {
   6324     int rv;
   6325     char *option;
   6326 
   6327     if (ARG_CNT(a) == 0) {
   6328         LOG_ERROR(BSL_LS_APPL_PHY,
   6329                   (BSL_META_U(unit, "Must specify REGister or UNREGister\n")));
   6330         return CMD_USAGE;
   6331     }
   6332     option = ARG_GET(a);
   6333     if (option == NULL) {
   6334         return CMD_USAGE;
   6335     }
   6336     if (prbs_stat_cmd_match(option, "REGister")) {
   6337         rv =  prbs_stat_handler_register(unit, prbs_stat_test_callback);
   6338     } else if (prbs_stat_cmd_match(option, "UNREGister")) {
   6339         rv =  prbs_stat_handler_unregister(unit, prbs_stat_test_callback);
   6340     } else {
   6341         LOG_ERROR(BSL_LS_APPL_PHY,
   6342                   (BSL_META_U(unit, "Must specify REGister or UNREGister\n")));
   6343         return CMD_USAGE;
   6344     }
   6345     return (rv == BCM_E_NONE) ? CMD_OK : CMD_FAIL;
   6346 }
   6347 
   6348 STATIC cmd_result_t
   6349 prbs_stat_cfg(int unit)
   6350 {
   6351     prbs_stat_cb_t *pscb;
   6352 
   6353     pscb = &(prbs_stat_cb[unit]);
   6354 
   6355     if (!PRBS_STAT_RUNNING(prbs_stat_cb[unit].flags)) {
   6356         LOG_CLI(("PRBSStat not started\n"));
   6357     } else {
   6358         char buf[512];
   6359         char pfmt[SOC_PBMP_FMT_LEN];
   6360 
   6361         format_bcm_pbmp(unit, buf, sizeof(buf), pscb->pbmp);
   6362         LOG_CLI(("PRBSStat: Polling interval: %d sec\n", pscb->secs));
   6363         LOG_CLI(("PRBSStat: Port bitmap: %s: %s\n",
   6364                  SOC_PBMP_FMT(pscb->pbmp, pfmt), buf));
   6365     }
   6366     return CMD_OK;
   6367 }
   6368 
   6369 /*** APIs ***/
   6370 /*
   6371  * Get computed BER for the last interval
   6372  *
   6373  * If the port is not configured with FEC or the BER cannot be computed,
   6374  * the BER is 0
   6375  *
   6376  * If successful, return 1; otherwise 0
   6377  */
   6378 int
   6379 prbs_stat_ber_get(int unit, bcm_port_t port, int lane, double *ber,
   6380                   int *interval)
   6381 {
   6382     prbs_stat_cb_t *pscb = &(prbs_stat_cb[unit]);
   6383     prbs_stat_pinfo_t *pspi = &(pscb->pinfo[port]);
   6384 
   6385     PRBS_STAT_LOCK(pscb->lock);
   6386     *ber = pspi->ber[lane];
   6387     *interval = pscb->secs;
   6388     PRBS_STAT_UNLOCK(pscb->lock);
   6389 
   6390     return 1;
   6391 }
   6392 
   6393 
   6394 /*
   6395  * Register handler function from the caller
   6396  */
   6397 int
   6398 prbs_stat_handler_register(int unit, prbs_stat_handler_func_t func)
   6399 {
   6400     int found = 0;
   6401     prbs_stat_cb_t *pscb = &(prbs_stat_cb[unit]);
   6402     prbs_stat_handler_t *h;
   6403 
   6404     if (!PRBS_STAT_INIT(pscb->flags)) {
   6405         LOG_CLI(("PRBSStat not initialized\n"));
   6406         return BCM_E_DISABLED;
   6407     }
   6408 
   6409     PRBS_STAT_LOCK(pscb->handler_lock);
   6410     for (h = pscb->handlers; h != NULL; h = h->next) {
   6411         if (h->func == func) {
   6412             found = TRUE;
   6413         }
   6414     }
   6415     /* Already registered */
   6416     if (found) {
   6417         PRBS_STAT_UNLOCK(pscb->handler_lock);
   6418         return BCM_E_NONE;
   6419     }
   6420 
   6421     h = sal_alloc(sizeof(prbs_stat_handler_t), "PRBSStat handler");
   6422     if (h == NULL) {
   6423         PRBS_STAT_UNLOCK(pscb->handler_lock);
   6424         return BCM_E_MEMORY;
   6425     }
   6426     /* Move current first node to second node */
   6427     h->next = pscb->handlers;
   6428     h->func = func;
   6429     /* Put the newly created node in the front of the list */
   6430     pscb->handlers = h;
   6431     PRBS_STAT_UNLOCK(pscb->handler_lock);
   6432 
   6433     return BCM_E_NONE;
   6434 }
   6435 
   6436 /*
   6437  * Unregister handler function from the caller
   6438  */
   6439 int
   6440 prbs_stat_handler_unregister(int unit, prbs_stat_handler_func_t func)
   6441 {
   6442     prbs_stat_cb_t *pscb = &(prbs_stat_cb[unit]);
   6443     prbs_stat_handler_t *h, *prev;
   6444 
   6445     if (!PRBS_STAT_INIT(pscb->flags)) {
   6446         LOG_CLI(("PRBSStat not initialized\n"));
   6447         return BCM_E_DISABLED;
   6448     }
   6449 
   6450     PRBS_STAT_LOCK(pscb->handler_lock);
   6451     for (prev = NULL, h = pscb->handlers; h != NULL; prev = h, h = h->next) {
   6452         if (h->func == func) {
   6453             if (prev == NULL) {
   6454                 pscb->handlers = h->next;
   6455             } else {
   6456                 prev->next = h->next;
   6457             }
   6458             break;
   6459         }
   6460     }
   6461     PRBS_STAT_UNLOCK(pscb->handler_lock);
   6462 
   6463     if (h != NULL) {
   6464         sal_free(h);
   6465         return BCM_E_NONE;
   6466     }
   6467     return BCM_E_NOT_FOUND;
   6468 }
   6469 
   6470 static char prbs_stat_usage[] =
   6471     "\nParameters: [STArt [Interval=<secs>]]\n"
   6472         "    [STOp] [Counters] [Ber] [CLear]\n";
   6473 
   6474 STATIC cmd_result_t 
   6475 _phy_diag_prbsstat(int unit, bcm_pbmp_t pbmp, args_t *a)
   6476 {
   6477     char *sc;
   6478 
   6479     /* Check if a unit is attached */
   6480     if (!sh_check_attached(ARG_CMD(a), unit)) {
   6481         return CMD_FAIL;
   6482     }
   6483 
   6484     if (!SOC_IS_TOMAHAWK3(unit)) {
   6485         return CMD_NOTIMPL;
   6486     }
   6487 
   6488     sc = ARG_GET(a);
   6489     /* check and display current configuration */
   6490     if (sc == NULL) {
   6491         return prbs_stat_cfg(unit);
   6492     }
   6493 
   6494     /* initialize */
   6495     if (!prbs_stat_init(unit)) {
   6496         return CMD_FAIL;
   6497     }
   6498 
   6499     if (prbs_stat_cmd_match(sc, "?")) {
   6500          LOG_CLI(("%s\n", prbs_stat_usage));
   6501     } else if (prbs_stat_cmd_match(sc, "STArt")) {
   6502         return prbs_stat_start(unit, pbmp, a);
   6503     } else if (prbs_stat_cmd_match(sc, "STOp")) {
   6504         return prbs_stat_stop(unit);
   6505     } else if (prbs_stat_cmd_match(sc, "Counters")) {
   6506         return prbs_stat_counter(unit, pbmp, a);
   6507     } else if (prbs_stat_cmd_match(sc, "Ber")) {
   6508         return prbs_stat_ber(unit, pbmp, a);
   6509     } else if (prbs_stat_cmd_match(sc, "CLear")) {
   6510         return prbs_stat_clear(unit, pbmp, a);
   6511     } else if (prbs_stat_cmd_match(sc, "Testcb")) {
   6512         return prbs_stat_callback_test(unit, a);
   6513     } else {
   6514         return CMD_USAGE;
   6515     }
   6516 
   6517     return CMD_OK;
   6518 }
   6519 
   6520 /* end of prbs_stat */
   6521 
   6522 /* start of fec_stat */
   6523 /* FECStat is a command that periodically collects FEC status counters such as
   6524  * corrected and uncorrected FEC codewords for a given port. The command then
   6525  * uses the corrected codewords to compute the pre-FEC bit error rate for the
   6526  * channel. FECStat can be used to collect FEC status counters anytime there is
   6527  * FEC traffic so there is no need to stop real traffic and dedicate the channel
   6528  * for diagnostics purposes.
   6529  */
   6530 #define FEC_STAT_F_INIT         (1 << 0)
   6531 #define FEC_STAT_F_RUNNING      (1 << 1)
   6532 
   6533 #define FEC_STAT_INIT(f)        (f & FEC_STAT_F_INIT)
   6534 #define FEC_STAT_RUNNING(f)     (f & FEC_STAT_F_RUNNING)
   6535 
   6536 #define FEC_STAT_LOCK(unit) \
   6537     if (fec_stat_cb[unit].lock) { \
   6538         sal_mutex_take(fec_stat_cb[unit].lock, sal_mutex_FOREVER);   \
   6539     }
   6540 
   6541 #define FEC_STAT_UNLOCK(unit) \
   6542     if (fec_stat_cb[unit].lock) { \
   6543         sal_mutex_give(fec_stat_cb[unit].lock); \
   6544     }
   6545 
   6546 typedef struct fec_stat_subcounter_s {
   6547     uint64 corrected;
   6548     uint64 uncorrected;
   6549     uint64 symbol_error[PM_MAX_LANES]; /* Per-lane based symbol error count. RS FEC only.*/
   6550 } fec_stat_subcounter_t;
   6551 
   6552 /*
   6553  * Acc: accummulated from beginning/last clear
   6554  * Cur: count since last time shown
   6555  */
   6556 typedef struct fec_stat_counter_s {
   6557     fec_stat_subcounter_t acc;
   6558     fec_stat_subcounter_t cur;
   6559 } fec_stat_counter_t;
   6560 
   6561 /*
   6562  * Per port info
   6563  */
   6564 typedef struct fec_stat_pinfo_s {
   6565     int speed;
   6566     int lanes;
   6567     bcm_port_phy_fec_t fec_type;
   6568     int intervals;
   6569     fec_stat_counter_t counters;/* Counters per port for this FEC */
   6570     double ber[PM_MAX_LANES];   /*  updated every interval */
   6571 } fec_stat_pinfo_t;
   6572 
   6573 typedef struct fec_stat_cb_ {
   6574     uint32 flags;
   6575     int secs;
   6576     int cfg_secs;
   6577     bcm_pbmp_t pbmp;
   6578     fec_stat_pinfo_t pinfo[BCM_PBMP_PORT_MAX];
   6579     sal_thread_t thread_id;
   6580     sal_mutex_t lock;
   6581     sal_sem_t sem;
   6582 } fec_stat_cb_t;
   6583 
   6584 fec_stat_cb_t fec_stat_cb[BCM_MAX_NUM_UNITS];
   6585 
   6586 /*
   6587  * Get FEC that is then used to key off which port phy control to issue
   6588  * to get FEC corrected/uncorrected counters
   6589  *
   6590  * Note that the counters are based on either BASE_R or RS FEC. RS FEC
   6591  * includes RS528, RS544, RS272 FEC
   6592  */
   6593 STATIC void
   6594 fec_stat_fec_type_get(int unit, bcm_port_t port, bcm_port_phy_fec_t *fec_type)
   6595 {
   6596     fec_stat_pinfo_t *fspi;
   6597 
   6598     fspi = &(fec_stat_cb[unit].pinfo[port]);
   6599 
   6600     *fec_type = fspi->fec_type;
   6601 
   6602     if ((fspi->fec_type == bcmPortPhyFecRs544) ||
   6603         (fspi->fec_type == bcmPortPhyFecRs272) ||
   6604         (fspi->fec_type == bcmPortPhyFecRs544_2xN) ||
   6605         (fspi->fec_type == bcmPortPhyFecRs272_2xN)) {
   6606         *fec_type = bcmPortPhyFecRsFec;
   6607     }
   6608 }
   6609 
   6610 /* This function will compute per-lane based BER for 1xN RS FEC and
   6611  * per-port based BER for BaseR FEC and 2xN RS FEC.
   6612  */
   6613 STATIC int
   6614 fec_stat_ber_compute(int unit, bcm_port_t port, uint32 delta, uint32* symb_delta,
   6615                      sal_time_t secs, double *ber)
   6616 {
   6617     int i;
   6618     double rate;
   6619     double nbits;
   6620     uint32 sum_symb_delta = 0;
   6621     fec_stat_pinfo_t *fspi;
   6622     bcm_port_phy_fec_t fec_type;
   6623 
   6624     if (secs < 1) {
   6625         return BCM_E_PARAM;
   6626     }
   6627 
   6628     fspi = &(fec_stat_cb[unit].pinfo[port]);
   6629     BCM_IF_ERROR_RETURN
   6630         (stat_speed_rate_get(fspi->speed, fspi->lanes, fspi->fec_type, &rate));
   6631     if (rate == 0) {
   6632         cli_out("Error: Unsupported speed mode: %d\n", port);
   6633         return BCM_E_UNAVAIL;
   6634     }
   6635     fec_stat_fec_type_get(unit, port, &fec_type);
   6636 
   6637     /* Rate needs to be adjusted from Gbps to bps */
   6638     rate = rate * 1024. * 1024. * 1024.;
   6639     /* Calculate per port BER for 2xN RS FEC based on sum of symbol error delta.
   6640      * Calculate per lane BER for other RS FEC based on symbol error delta.
   6641      * Calculate per port BER for other FEC types based on block error delta.
   6642      */
   6643     if ((fspi->fec_type == bcmPortPhyFecRs544_2xN) ||
   6644         (fspi->fec_type == bcmPortPhyFecRs272_2xN)) {
   6645         nbits = rate * fspi->lanes;
   6646         for (i = 0; i < fspi->lanes; i++) {
   6647             sum_symb_delta += symb_delta[i];
   6648         }
   6649         /* Per port BER stored in ber[0]. */
   6650         ber[0] = sum_symb_delta / (nbits * secs);
   6651         LOG_DEBUG(BSL_LS_APPL_PHY,
   6652                   (BSL_META_U(unit, "Updated BER for port %d: %8.2e\n"),
   6653                    port, ber[0]));
   6654     } else if (fec_type == bcmPortPhyFecRsFec) {
   6655         nbits = rate;
   6656         for (i = 0; i < fspi->lanes; i++) {
   6657             ber[i] = symb_delta[i] / (nbits * secs);
   6658             LOG_DEBUG(BSL_LS_APPL_PHY,
   6659                       (BSL_META_U(unit, "Updated BER for port %d lane %d: %8.2e\n"),
   6660                        port, i, ber[i]));
   6661 
   6662         }
   6663     } else {
   6664         /* Per port BER stored in ber[0]. */
   6665         nbits = rate * fspi->lanes;
   6666         ber[0] = delta / (nbits * secs);
   6667         LOG_DEBUG(BSL_LS_APPL_PHY,
   6668                   (BSL_META_U(unit, "Updated BER for port %d: %8.2e\n"),
   6669                    port, ber[0]));
   6670 
   6671     }
   6672 
   6673     return BCM_E_NONE;
   6674 }
   6675 
   6676 STATIC void
   6677 fec_stat_counter_show(char *cname, char *pname, int* lane,
   6678                       uint64 acc_counter, uint64 cur_counter, sal_time_t secs)
   6679 {
   6680     char chdr[32];
   6681     char buf[64];
   6682     uint64 delta;
   6683 
   6684     if (lane != NULL) {
   6685         sal_sprintf(chdr, "%s.%s[%d]", cname, pname, *lane);
   6686     } else {
   6687         sal_sprintf(chdr, "%s.%s", cname, pname);
   6688     }
   6689 
   6690     delta = acc_counter;
   6691     COMPILER_64_SUB_64(delta, cur_counter);
   6692     if (!COMPILER_64_IS_ZERO(delta)) {
   6693         format_uint64_decimal(buf, acc_counter, ',');
   6694         LOG_CLI(("%-25s: %20s", chdr, buf));
   6695 
   6696         /* Show counters since last show */
   6697         format_uint64_decimal(buf, delta, ',');
   6698         LOG_CLI(("  %20s",buf));
   6699 
   6700         /* Show counters per second */
   6701         COMPILER_64_UDIV_32(delta, (uint32)secs);
   6702         format_uint64_decimal(buf, delta, ',');
   6703         LOG_CLI(("  %12s/s\n",buf));
   6704     }
   6705 }
   6706 
   6707 STATIC int
   6708 fec_stat_port_counter(int unit, bcm_port_t port)
   6709 {
   6710     int secs, lane, symb_err_valid = 0;
   6711     bcm_port_phy_fec_t fec_type;
   6712     fec_stat_cb_t *fscb;
   6713     fec_stat_pinfo_t *fspi;
   6714     fec_stat_counter_t *fsco;
   6715     char *corrected_name;
   6716     char *uncorrected_name;
   6717     char *symbol_error_name = "RS_SYMBOL_ERR";
   6718     fscb = &(fec_stat_cb[unit]);
   6719     fspi = &(fscb->pinfo[port]);
   6720     fsco = &(fspi->counters);
   6721 
   6722     fec_stat_fec_type_get(unit, port, &fec_type);
   6723     if (fec_type == bcmPortPhyFecRsFec) {
   6724         corrected_name = "CORREC_RS_CW";
   6725         uncorrected_name = "UNCORREC_RS_CW";
   6726         if ((fspi->fec_type != bcmPortPhyFecRs544_2xN) &&
   6727             (fspi->fec_type != bcmPortPhyFecRs272_2xN)) {
   6728             symb_err_valid = 1;
   6729         }
   6730     } else {
   6731         corrected_name = "CORREC_BASER";
   6732         uncorrected_name = "UNCORREC_BASER";
   6733     }
   6734 
   6735     secs = fscb->secs * fspi->intervals;
   6736     fec_stat_counter_show(corrected_name, BCM_PORT_NAME(unit, port), NULL,
   6737                           fsco->acc.corrected, fsco->cur.corrected,
   6738                           secs);
   6739     fec_stat_counter_show(uncorrected_name, BCM_PORT_NAME(unit, port), NULL,
   6740                           fsco->acc.uncorrected, fsco->cur.uncorrected,
   6741                           secs);
   6742     if (symb_err_valid) {
   6743         for (lane = 0; lane < fspi->lanes; lane++) {
   6744             fec_stat_counter_show(symbol_error_name, BCM_PORT_NAME(unit, port), &lane,
   6745                                   fsco->acc.symbol_error[lane], fsco->cur.symbol_error[lane],
   6746                                   secs);
   6747             fsco->cur.symbol_error[lane] = fsco->acc.symbol_error[lane];
   6748         }
   6749     }
   6750     fspi->intervals = 0;
   6751     fsco->cur.corrected = fsco->acc.corrected;
   6752     fsco->cur.uncorrected = fsco->acc.uncorrected;
   6753 
   6754     return BCM_E_NONE;
   6755 }
   6756 
   6757 
   6758 STATIC void
   6759 fec_stat_accumulate(int unit, bcm_port_t port, bcm_port_phy_control_t type,
   6760                     uint64 *subc, uint32 *out_count)
   6761 {
   6762     int rv;
   6763     uint32 count;
   6764 
   6765     rv = bcm_port_phy_control_get(unit, port, type, &count);
   6766     if (BCM_FAILURE(rv)) {
   6767         count = 0;
   6768     }
   6769     if (count) {
   6770         COMPILER_64_ADD_32(*subc, count);
   6771     }
   6772     *out_count = count;
   6773 }
   6774 
   6775 
   6776 STATIC int
   6777 fec_stat_ber_update(int unit, bcm_port_t port, uint32 delta, uint32* symb_delta)
   6778 {
   6779     int rv = 0;
   6780     fec_stat_cb_t *fscb;
   6781     fec_stat_pinfo_t *fspi;
   6782 
   6783     fscb = &(fec_stat_cb[unit]);
   6784     fspi = &(fscb->pinfo[port]);
   6785 
   6786     rv = fec_stat_ber_compute(unit, port, delta, symb_delta, fscb->secs, fspi->ber);
   6787 
   6788     return rv;
   6789 }
   6790 
   6791 /*
   6792  * If there is a port configuration change, update the new configuration
   6793  * and clear counters, BER
   6794  */
   6795 STATIC int
   6796 fec_stat_pinfo_update(int unit, bcm_port_t port)
   6797 {
   6798     fec_stat_pinfo_t *fspi;
   6799     fec_stat_counter_t *fsco;
   6800     bcm_port_resource_t rsrc;
   6801 
   6802     fspi = &(fec_stat_cb[unit].pinfo[port]);
   6803 
   6804     BCM_IF_ERROR_RETURN(bcm_port_resource_speed_get(unit, port, &rsrc));
   6805     if ((fspi->speed == rsrc.speed) &&
   6806         (fspi->lanes == rsrc.lanes) &&
   6807         (fspi->fec_type == rsrc.fec_type)) {
   6808         return BCM_E_NONE;
   6809     }
   6810 
   6811     LOG_DEBUG(BSL_LS_APPL_PHY,
   6812               (BSL_META_U(unit, "Updating %s config\n"),
   6813                BCM_PORT_NAME(unit, port)));
   6814 
   6815     fspi->speed = rsrc.speed;
   6816     fspi->lanes = rsrc.lanes;
   6817     fspi->fec_type = rsrc.fec_type;
   6818 
   6819     sal_memset(fspi->ber, 0, PM_MAX_LANES * sizeof(double));
   6820 
   6821     fsco = &(fspi->counters);
   6822     sal_memset(&(fsco->acc), 0, sizeof(fec_stat_subcounter_t));
   6823     sal_memset(&(fsco->cur), 0, sizeof(fec_stat_subcounter_t));
   6824 
   6825     return BCM_E_NONE;
   6826 }
   6827 
   6828 
   6829 STATIC cmd_result_t
   6830 fec_stat_collect(int unit, bcm_port_t port)
   6831 {
   6832     bcm_error_t rv = BCM_E_NONE;
   6833     uint32 count, corrected_count, error_count[PM_MAX_LANES];
   6834     soc_port_phy_rsfec_symb_errcnt_t symbol_error_count;
   6835     uint32 inst;
   6836     int i, corrected_ctrl, uncorrected_ctrl, symbol_err_valid = 0;
   6837     bcm_port_phy_fec_t fec_type;
   6838     fec_stat_pinfo_t *fspi;
   6839     fec_stat_counter_t *fsco;
   6840 
   6841     FEC_STAT_LOCK(unit);
   6842 
   6843     rv = fec_stat_pinfo_update(unit, port);
   6844     if (rv != BCM_E_NONE) {
   6845         FEC_STAT_UNLOCK(unit);
   6846         return CMD_FAIL;
   6847     }
   6848 
   6849     fspi = &(fec_stat_cb[unit].pinfo[port]);
   6850     fsco = &(fspi->counters);
   6851 
   6852     fec_stat_fec_type_get(unit, port, &fec_type);
   6853 
   6854     if (fec_type == bcmPortPhyFecRsFec) {
   6855         corrected_ctrl = BCM_PORT_PHY_CONTROL_FEC_CORRECTED_CODEWORD_COUNT;
   6856         uncorrected_ctrl = BCM_PORT_PHY_CONTROL_FEC_UNCORRECTED_CODEWORD_COUNT;
   6857         symbol_err_valid = 1;
   6858     } else {   /* Assume other FEC is BaseR */
   6859         corrected_ctrl = BCM_PORT_PHY_CONTROL_FEC_CORRECTED_BLOCK_COUNT;
   6860         uncorrected_ctrl = BCM_PORT_PHY_CONTROL_FEC_UNCORRECTED_BLOCK_COUNT;
   6861     }
   6862 
   6863     fec_stat_accumulate(unit, port, uncorrected_ctrl, &(fsco->acc.uncorrected),
   6864                         &count);
   6865     fec_stat_accumulate(unit, port, corrected_ctrl, &(fsco->acc.corrected),
   6866                         &corrected_count);
   6867     if (symbol_err_valid) {
   6868         symbol_error_count.max_count = PM_MAX_LANES;
   6869         symbol_error_count.symbol_errcnt = error_count;
   6870         inst = PHY_DIAG_INSTANCE(PHY_DIAG_DEV_INT , PHY_DIAG_INTF_DFLT, PHY_DIAG_LN_DFLT);
   6871         rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD,
   6872                              PHY_DIAG_CTRL_RSFEC_SYMB_ERR, (void *)&symbol_error_count);
   6873         if (rv != BCM_E_NONE) {
   6874             FEC_STAT_UNLOCK(unit);
   6875             return CMD_FAIL;
   6876         }
   6877         if (symbol_error_count.actual_count != fspi->lanes) {
   6878             /* If actual_count returned by the API does not equal to
   6879              * number of lanes stored in DB, it means the speed configs in
   6880              * DB is not up-to-date.
   6881              */
   6882             FEC_STAT_UNLOCK(unit);
   6883             return CMD_FAIL;
   6884         }
   6885         for (i = 0; i < fspi->lanes; i++) {
   6886             COMPILER_64_ADD_32(fsco->acc.symbol_error[i], error_count[i]);
   6887         }
   6888     }
   6889 
   6890     rv = fec_stat_ber_update(unit, port, corrected_count, error_count);
   6891 
   6892     fspi->intervals++;
   6893 
   6894     FEC_STAT_UNLOCK(unit);
   6895     return CMD_OK;
   6896 }
   6897 
   6898 STATIC void
   6899 fec_stat_thread(int unit)
   6900 {
   6901     int u_interval;
   6902     bcm_port_t port;
   6903     fec_stat_cb_t *fscb;
   6904 
   6905     fscb = &(fec_stat_cb[unit]);
   6906     u_interval = fscb->secs * 1000000;
   6907 
   6908     LOG_CLI(("FEC stat thread started...\n"));
   6909     while (fscb->secs) {
   6910         BCM_PBMP_ITER(fscb->pbmp, port) {
   6911             LOG_DEBUG(BSL_LS_APPL_PHY,
   6912                       (BSL_META_U(unit, "Collect FEC for port %d\n"), port));
   6913             if (fec_stat_collect(unit, port)) {
   6914                 LOG_ERROR(BSL_LS_APPL_PHY,
   6915                           (BSL_META_U(
   6916                               unit,
   6917                               "Failed collect FEC stats for port %d\n"), port));
   6918             }
   6919         }
   6920         sal_sem_take(fscb->sem, u_interval);
   6921     }
   6922 
   6923     LOG_DEBUG(BSL_LS_APPL_PHY, ("FEC stat thread exiting...\n"));
   6924     sal_memset(fscb, 0, sizeof(fec_stat_cb_t));
   6925     fscb->thread_id = NULL;
   6926     sal_thread_exit(0);
   6927 }
   6928 
   6929 
   6930 STATIC int
   6931 fec_stat_init(int unit)
   6932 {
   6933     fec_stat_cb_t *fscb;
   6934 
   6935     fscb = &(fec_stat_cb[unit]);
   6936     if (FEC_STAT_INIT(fscb->flags)) {
   6937         return BCM_E_NONE;
   6938     }
   6939     sal_memset(fscb, 0, sizeof(fec_stat_cb_t));
   6940     fscb->flags = FEC_STAT_F_INIT;
   6941 
   6942     if ((fscb->lock = sal_mutex_create("FECStat lock")) == NULL)
   6943         return BCM_E_INTERNAL;
   6944 
   6945     if ((fscb->sem = sal_sem_create("FECStat sleep", sal_sem_BINARY, 0)) == NULL)
   6946         return BCM_E_INTERNAL;
   6947 
   6948     return BCM_E_NONE;
   6949 }
   6950 
   6951 STATIC int
   6952 fec_stat_clear(int unit, bcm_pbmp_t pbmp, args_t *a)
   6953 {
   6954     bcm_port_t port;
   6955 
   6956     FEC_STAT_LOCK(unit);
   6957     BCM_PBMP_ITER(pbmp, port) {
   6958         sal_memset(&(fec_stat_cb[unit].pinfo[port].counters),
   6959                    0, sizeof(fec_stat_counter_t));
   6960     }
   6961     FEC_STAT_UNLOCK(unit);
   6962     return CMD_OK;
   6963 }
   6964 
   6965 STATIC int
   6966 fec_stat_counters(int unit, bcm_pbmp_t pbmp, args_t *a)
   6967 {
   6968     int rv = 0;
   6969     bcm_port_t port;
   6970 
   6971     FEC_STAT_LOCK(unit);
   6972     LOG_CLI(("%-20s\t\t%20s\t%20s\t%12s",
   6973         "port", "accumulated count", "last count", "count per sec\n"));
   6974     BCM_PBMP_ITER(pbmp, port) {
   6975         rv = fec_stat_port_counter(unit, port);
   6976         if (rv) {
   6977             break;
   6978         }
   6979     }
   6980     FEC_STAT_UNLOCK(unit);
   6981 
   6982     return rv ? CMD_FAIL : CMD_OK;
   6983 }
   6984 
   6985 STATIC int
   6986 fec_stat_ber(int unit, bcm_pbmp_t pbmp, args_t *a)
   6987 {
   6988     bcm_port_t port;
   6989     fec_stat_pinfo_t *fspi;
   6990     bcm_port_phy_fec_t fec_type;
   6991     int lane;
   6992 
   6993     FEC_STAT_LOCK(unit);
   6994     /* Show BER computed during last interval */
   6995     LOG_CLI(("%-10s   %s", "port", "BER\n"));
   6996     LOG_CLI(("====\n"));
   6997     BCM_PBMP_ITER(pbmp, port) {
   6998         fspi = &(fec_stat_cb[unit].pinfo[port]);
   6999         fec_stat_fec_type_get(unit, port, &fec_type);
   7000         if ((fspi->fec_type == bcmPortPhyFecRs544_2xN) ||
   7001             (fspi->fec_type == bcmPortPhyFecRs272_2xN)) {
   7002             if (fspi->ber[0]) {
   7003                 LOG_CLI(("%-10s:  %4.2e\n", BCM_PORT_NAME(unit, port), fspi->ber[0]));
   7004             } else {
   7005                 LOG_CLI(("%-10s:  N/A\n", BCM_PORT_NAME(unit, port)));
   7006             }
   7007         } else if (fec_type == bcmPortPhyFecRsFec) {
   7008             for (lane = 0; lane < fspi->lanes; lane++) {
   7009                 if (fspi->ber[lane]) {
   7010                     LOG_CLI(("%-s[%d]:  %4.2e\n", BCM_PORT_NAME(unit, port), lane, fspi->ber[lane]));
   7011                 } else {
   7012                     LOG_CLI(("%-s[%d]:  N/A\n", BCM_PORT_NAME(unit, port), lane));
   7013                 }
   7014             }
   7015         } else {
   7016             if (fspi->ber[0]) {
   7017                 LOG_CLI(("%-10s:  %4.2e\n", BCM_PORT_NAME(unit, port), fspi->ber[0]));
   7018             } else {
   7019                 LOG_CLI(("%-10s:  N/A\n", BCM_PORT_NAME(unit, port)));
   7020             }
   7021         }
   7022     }
   7023     FEC_STAT_UNLOCK(unit);
   7024     return CMD_OK;
   7025 }
   7026 
   7027 
   7028 STATIC int
   7029 fec_stat_stop(int unit)
   7030 {
   7031     fec_stat_cb_t *fscb;
   7032 
   7033     fscb = &(fec_stat_cb[unit]);
   7034     if (FEC_STAT_RUNNING(fscb->flags)) {
   7035         fscb->secs = 0;
   7036         fscb->flags &= ~FEC_STAT_F_RUNNING;
   7037         LOG_CLI(("Stopping FECStat thread\n"));
   7038         sal_sem_give(fscb->sem);
   7039     }
   7040     return CMD_OK;
   7041 }
   7042 
   7043 STATIC int
   7044 fec_stat_counter_init(int unit)
   7045 {
   7046     uint32 inst, value, error_count[PM_MAX_LANES];
   7047     soc_port_phy_rsfec_symb_errcnt_t symbol_error_count;
   7048     bcm_port_phy_fec_t fec_type;
   7049     bcm_port_t port;
   7050     fec_stat_pinfo_t *fspi;
   7051     fec_stat_cb_t *fscb;
   7052 
   7053     fscb = &(fec_stat_cb[unit]);
   7054 
   7055     BCM_PBMP_ITER(fscb->pbmp, port) {
   7056         fspi = &(fec_stat_cb[unit].pinfo[port]);
   7057         sal_memset(&(fspi->counters), 0, sizeof(fec_stat_counter_t));
   7058         BCM_IF_ERROR_RETURN(fec_stat_pinfo_update(unit, port));
   7059 
   7060         /* Prime counters to avoid first read to get all values since reboot */
   7061         fec_stat_fec_type_get(unit, port, &fec_type);
   7062         if (fec_type == bcmPortPhyFecRsFec) {
   7063             symbol_error_count.max_count = PM_MAX_LANES;
   7064             symbol_error_count.symbol_errcnt = error_count;
   7065             inst = PHY_DIAG_INSTANCE(PHY_DIAG_DEV_INT , PHY_DIAG_INTF_DFLT, PHY_DIAG_LN_DFLT);
   7066             BCM_IF_ERROR_RETURN(port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD,
   7067                                 PHY_DIAG_CTRL_RSFEC_SYMB_ERR, (void *)&symbol_error_count));
   7068 
   7069             BCM_IF_ERROR_RETURN(bcm_port_phy_control_get(unit, port,
   7070                                 BCM_PORT_PHY_CONTROL_FEC_CORRECTED_CODEWORD_COUNT,
   7071                                 &value));
   7072             BCM_IF_ERROR_RETURN(bcm_port_phy_control_get(unit, port,
   7073                                 BCM_PORT_PHY_CONTROL_FEC_UNCORRECTED_CODEWORD_COUNT,
   7074                                 &value));
   7075         } else {
   7076             BCM_IF_ERROR_RETURN(bcm_port_phy_control_get(unit, port,
   7077                                 BCM_PORT_PHY_CONTROL_FEC_CORRECTED_BLOCK_COUNT,
   7078                                 &value));
   7079             BCM_IF_ERROR_RETURN(bcm_port_phy_control_get(unit, port,
   7080                                 BCM_PORT_PHY_CONTROL_FEC_UNCORRECTED_BLOCK_COUNT,
   7081                                 &value));
   7082         }
   7083     }
   7084     return BCM_E_NONE;
   7085 }
   7086 
   7087 STATIC int
   7088 fec_stat_start(int unit, bcm_pbmp_t pbmp, args_t *a)
   7089 {
   7090     int secs, rv;
   7091     parse_table_t   pt;
   7092     fec_stat_cb_t *fscb;
   7093 
   7094     fscb = &(fec_stat_cb[unit]);
   7095 
   7096     if (ARG_CNT(a) == 0) {
   7097         if (!(fscb->flags & FEC_STAT_F_RUNNING)) {
   7098             LOG_CLI(("FECStat: not running\n"));
   7099         } else {
   7100             char pbmp_str[SOC_PBMP_FMT_LEN];
   7101             SOC_PBMP_FMT(fscb->pbmp, pbmp_str);
   7102             LOG_CLI(("FECStat: interval=%ds\n", fscb->secs));
   7103             LOG_CLI(("FECStat: pbmp=%s\n", pbmp_str));
   7104         }
   7105         return CMD_OK;
   7106     }
   7107 
   7108     /*SOC_PBMP_ASSIGN(pbmp, fscb->pbmp);*/
   7109     secs = fscb->secs;
   7110 
   7111     parse_table_init(unit, &pt);
   7112     parse_table_add(&pt, "Interval", PQ_DFL|PQ_INT, 0, &secs, NULL);
   7113     /*parse_table_add(&pt, "PortBitMap",PQ_DFL|PQ_PBMP, 0, &pbmp, NULL);*/
   7114 
   7115     if (parse_arg_eq(a, &pt) < 0) {
   7116         cli_out("%s: Error: Unknown option: %s\n", ARG_CMD(a), ARG_CUR(a));
   7117         parse_arg_eq_done(&pt);
   7118         return CMD_FAIL;
   7119     }
   7120     parse_arg_eq_done(&pt);
   7121 
   7122     if (secs == 0 || secs > 180) {
   7123         LOG_CLI(("Interval must be between 1 and 180 seconds\n"));
   7124         return CMD_FAIL;
   7125     }
   7126 
   7127     /*
   7128      * Allow start to be called while already running to update
   7129      * interval and pbmp
   7130      */
   7131     if (fscb->flags & FEC_STAT_F_RUNNING) {
   7132         FEC_STAT_LOCK(unit);
   7133     }
   7134 
   7135     fscb->secs = secs;
   7136     SOC_PBMP_ASSIGN(fscb->pbmp, pbmp);
   7137 
   7138     rv = fec_stat_counter_init(unit);
   7139 
   7140     if (fscb->flags & FEC_STAT_F_RUNNING) {
   7141         /*
   7142          * If fec_stat is already running,
   7143          * need to return without starting new thread.
   7144          */
   7145         FEC_STAT_UNLOCK(unit);
   7146         return (rv == BCM_E_NONE) ? CMD_OK : CMD_FAIL;
   7147     }
   7148 
   7149     if (rv != BCM_E_NONE) {
   7150         return CMD_FAIL;
   7151     }
   7152 
   7153     fscb->thread_id = sal_thread_create("FECstat",
   7154                                       SAL_THREAD_STKSZ,
   7155                                       100,   /* thread priority */
   7156                                       (void (*)(void*))fec_stat_thread,
   7157                                       INT_TO_PTR(unit));
   7158     if (fscb->thread_id == SAL_THREAD_ERROR) {
   7159         LOG_ERROR(
   7160             BSL_LS_APPL_PHY,
   7161             (BSL_META_U(unit, "Could not create FECstat thread\n")));
   7162         fscb->flags &= ~FEC_STAT_F_RUNNING;
   7163         return CMD_FAIL;
   7164     }
   7165     fscb->flags |= FEC_STAT_F_RUNNING;
   7166 
   7167     return CMD_OK;
   7168 }
   7169 
   7170 /*
   7171  * Match input with key. Allows abbreviated matches based on
   7172  * the minimum initial capital letters in key. For example,
   7173  * key = ABCdef will be matched with the input
   7174  * abc, abcd, abcde, abcdef. Any other input is a mismatch.
   7175  */
   7176 STATIC int
   7177 fec_stat_cmd_match(char *inp, char *key)
   7178 {
   7179     while (*key && isupper(*key)) {
   7180         if (!*inp || (toupper(*inp) != *key)) {
   7181             return 0;
   7182         }
   7183         key++;
   7184         inp++;
   7185     }
   7186     while (*inp) {
   7187         if (toupper(*inp) != toupper(*key)) {
   7188             return 0;
   7189         }
   7190         key++;
   7191         inp++;
   7192     }
   7193     return 1;
   7194 }
   7195 
   7196 STATIC cmd_result_t
   7197 fec_stat_cfg(int unit)
   7198 {
   7199     fec_stat_cb_t *fscb;
   7200 
   7201     fscb = &(fec_stat_cb[unit]);
   7202 
   7203     if (!FEC_STAT_RUNNING(fec_stat_cb[unit].flags)) {
   7204         LOG_CLI(("FECStat not started\n"));
   7205     } else {
   7206         char buf[512];
   7207         char pfmt[SOC_PBMP_FMT_LEN];
   7208 
   7209         format_bcm_pbmp(unit, buf, sizeof(buf), fscb->pbmp);
   7210         LOG_CLI(("FECStat: Polling interval: %d sec\n", fscb->secs));
   7211         LOG_CLI(("FECStat: Port bitmap: %s: %s\n",
   7212                  SOC_PBMP_FMT(fscb->pbmp, pfmt), buf));
   7213     }
   7214     return CMD_OK;
   7215 }
   7216 
   7217 /*** API ***/
   7218 /*
   7219  * Get computed BER for the last <secs>
   7220  *
   7221  * If the port is not configured with FEC or the BER cannot be computed,
   7222  * the BER is 0
   7223  *
   7224  * If successful, return 1; otherwise 0
   7225  */
   7226 int
   7227 fec_stat_ber_get(int unit, bcm_port_t port, int *lane, double *ber)
   7228 {
   7229     fec_stat_pinfo_t *fscb = &(fec_stat_cb[unit].pinfo[port]);
   7230 
   7231     FEC_STAT_LOCK(unit);
   7232     if (lane == NULL) {
   7233         *ber = fscb->ber[0];
   7234     } else if ((*lane >= 0) && (*lane < PM_MAX_LANES)) {
   7235         *ber = fscb->ber[*lane];
   7236     } else {
   7237         return 0;
   7238     }
   7239 
   7240     FEC_STAT_UNLOCK(unit);
   7241 
   7242     return 1;
   7243 
   7244 }
   7245 
   7246 static char fec_stat_usage[] =
   7247     "\nParameters: [STArt [Interval=<secs>]]\n"
   7248         "    [STOp] [Counters] [Ber] [CLear]\n";
   7249 
   7250 STATIC cmd_result_t
   7251 _phy_diag_fecstat(int unit, bcm_pbmp_t pbmp, args_t *a)
   7252 {
   7253     char *sc;
   7254 
   7255     if (!sh_check_attached(ARG_CMD(a), unit)) {
   7256         return CMD_FAIL;
   7257     }
   7258 
   7259     if (!SOC_IS_TOMAHAWK3(unit)) {
   7260         return CMD_NOTIMPL;
   7261     }
   7262 
   7263     sc = ARG_GET(a);
   7264     if (sc == NULL) {
   7265         return fec_stat_cfg(unit);
   7266     }
   7267 
   7268     if (fec_stat_init(unit)) {
   7269         return CMD_FAIL;
   7270     }
   7271     if (fec_stat_cmd_match(sc, "?")) {
   7272          LOG_CLI(("%s\n", fec_stat_usage));
   7273     }
   7274     else if (fec_stat_cmd_match(sc, "STArt")) {
   7275         return fec_stat_start(unit, pbmp, a);
   7276     } else if (fec_stat_cmd_match(sc, "STOp")) {
   7277         return fec_stat_stop(unit);
   7278     } else if (fec_stat_cmd_match(sc, "Counters")) {
   7279         return fec_stat_counters(unit, pbmp, a);
   7280     } else if (fec_stat_cmd_match(sc, "Ber")) {
   7281         return fec_stat_ber(unit, pbmp, a);
   7282     } else if (fec_stat_cmd_match(sc, "CLear")) {
   7283         return fec_stat_clear(unit, pbmp, a);
   7284     } else {
   7285         return CMD_USAGE;
   7286     }
   7287 
   7288     return CMD_OK;
   7289 }
   7290 
   7291 /* end of fec_stat */
   7292 #endif /* BCM_TOMAHAWK3_SUPPORT */
   7293 
   7294 /* 
   7295  * Diagnostic utilities for serdes and PHY devices.
   7296  *
   7297  * Command format used in BCM diag shell:
   7298  * phy diag <pbm> <sub_cmd> [sub cmd parameters]
   7299  * All sub commands take two general parameters: unit and if. This identifies
   7300  * the instance the command targets to.
   7301  * unit = 0,1, ....  
   7302  *   unit takes numeric values identifying the instance of the PHY devices 
   7303  *   associated with the given port. A value 0 indicates the internal 
   7304  *   PHY(serdes) the one directly connected to the MAC. A value 1 indicates
   7305  *   the first external PHY.
   7306  * if(interface) = [sys | line] 
   7307  *   interface identifies the system side interface or line side interface of
   7308  *   PHY device.
   7309  * The list of sub commands:
   7310  *   dsc - display tx/rx equalization information. Warpcore(WC) only.
   7311  *   veye - vertical eye margin mesurement. WC only. All eye margin functions
   7312  *          are used in conjunction with PRBS utility in the configed speed mode
   7313  *   heye_r - right horizontal eye margin mesurement. WC only 
   7314  *   heye_l - right horizontal eye margin mesurement. WC only 
   7315  *   for the WarpLite, there are three additional parameters, live link or not, par1 for the target BER value for example: -18 stands for 10^(-18)
   7316  *   par2 will be percentage range for example, 5 means checxk for +-%5 of the target BER
   7317  *   loopback - put the device in the given loopback mode 
   7318  *              parameter: mode=[remote | local | none]
   7319  *   prbs - perform various PRBS functions. Takes all parameters of the
   7320  *          "phy prbs" command except the mode parameter.
   7321  *          Example:
   7322  *            A port has a WC serdes and 84740 PHY connected. A typical usage
   7323  *            is to use the PRBS to check the link between WC and the system
   7324  *            side of the 84740. Use port xe0 as an example:
   7325  *            BCM.0> phy diag xe0 prbs set unit=0 p=3
   7326  *            BCM.0> phy diag xe0 prbs set unit=1 if=sys p=3
   7327  *            BCM.0> phy diag xe0 prbs get unit=1 if=sys
   7328  *            BCM.0> phy diag xe0 prbs get unit=0
   7329  *
   7330  *   prbsstat - periodically collect PRBS error counters an
   7331  *           compute BER based on the port configuration an
   7332  *           the observed error counters.
   7333  *           Parameters:
   7334  *             [STArt [Interval=<secs>]]
   7335  *             [STOp]
   7336  *             [Counters]
   7337  *             [Ber]
   7338  *             [Clear]
   7339  *          Example:
   7340  *            BCM.0> phy diag cd0-cd3 prbsstat
   7341  *            BCM.0> phy diag cd0-cd3 prbsstat start i=60
   7342  *            BCM.0> phy diag cd0-cd3 prbsstat counters
   7343  *            BCM.0> phy diag cd0-cd3 prbsstat ber
   7344  *            BCM.0> phy diag cd0-cd3 prbsstat clear
   7345  *   pcs - display Diag information
   7346  *            BCM.0> phy diag xe0 pcs
   7347  *            BCM.0> phy diag xe0 pcs topology
   7348  *            BCM.0> phy diag xe0 pcs link
   7349  *            BCM.0> phy diag xe0 pcs aneg
   7350  *            BCM.0> phy diag xe0 pcs state
   7351  *            BCM.0> phy diag xe0 pcs tfc
   7352  *            BCM.0> phy diag xe0 pcs antimers
   7353  *
   7354  *   dsc - display Diag information
   7355  *            BCM.0> phy diag xe0 dsc
   7356  *            BCM.0> phy diag xe0 dsc config
   7357  *            BCM.0> phy diag xe0 dsc cl72
   7358  *            BCM.0> phy diag xe0 dsc debug
   7359  *
   7360  *   mfg - run manufacturing test on PHY BCM8483X
   7361  *              parameter: (t)est=num (d)ata=<val> (f)ile=filename
   7362  *              Test should be : 
   7363  *              1 (HYB_CANC), needs (f)ile=filename 
   7364  *              2 (DENC),     needs (f)ile=filename 
   7365  *              3 (TX_ON)     needs (d)ata = bit map for turning TX off on pairs DCBA
   7366  *              0 (EXIT)
   7367  */
   7368 STATIC cmd_result_t
   7369 _if_esw_phy_diag(int unit, args_t *args)
   7370 {
   7371     bcm_port_t port, dport;
   7372     bcm_pbmp_t pbmp;
   7373     int rv, cmd;
   7374     int par[5];
   7375     int *pData;
   7376     int lscan_time;
   7377     char *cmd_str, *port_str;
   7378     parse_table_t pt;
   7379     bcm_port_t p;
   7380     int lnk_mode[BCM_PBMP_PORT_MAX];
   7381 
   7382     rv = CMD_OK;
   7383     par[0] = 0;
   7384     par[1] = 0;
   7385     par[2] = 0;
   7386     par[3] = 0;
   7387     par[4] = 0;
   7388     pData = &par[0];
   7389 
   7390     sal_memset(&lnk_mode, -1, sizeof(lnk_mode));
   7391 
   7392     if ((port_str = ARG_GET(args)) == NULL) {
   7393         return CMD_USAGE;
   7394     }
   7395 
   7396     BCM_PBMP_CLEAR(pbmp);
   7397     if (parse_bcm_pbmp(unit, port_str, &pbmp) < 0) {
   7398         cli_out("Error: unrecognized port bitmap: %s\n", port_str);
   7399         return CMD_FAIL;
   7400     }
   7401 
   7402     if ((cmd_str = ARG_GET(args)) == NULL) {
   7403         return CMD_USAGE;
   7404     }
   7405 
   7406     /* linkscan should be disabled. soc_phyctrl_diag_ctrl() doesn't
   7407      * assume exclusive access to the device.
   7408      */
   7409     BCM_IF_ERROR_RETURN(bcm_linkscan_enable_get(unit, &lscan_time));
   7410     if (lscan_time != 0) {
   7411         BCM_PBMP_ITER(pbmp, p) {
   7412             BCM_IF_ERROR_RETURN(bcm_linkscan_mode_get(unit, p, &lnk_mode[p]));
   7413             if (lnk_mode[p] != BCM_LINKSCAN_MODE_NONE) {
   7414                 BCM_IF_ERROR_RETURN(bcm_linkscan_mode_set(unit, p, BCM_LINKSCAN_MODE_NONE));
   7415             }
   7416         }
   7417     }
   7418     if (sal_strcasecmp(cmd_str, "peek") == 0) {
   7419         cmd = PHY_DIAG_CTRL_PEEK;
   7420         parse_table_init(unit, &pt);
   7421         parse_table_add(&pt, "fb", PQ_DFL | PQ_INT, (void *)(0), pData++, NULL);
   7422         parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0),
   7423                         pData++, NULL);
   7424         if (parse_arg_eq(args, &pt) < 0) {
   7425             cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   7426             parse_arg_eq_done(&pt);
   7427             return CMD_USAGE;
   7428         }
   7429         /* command targets to Internal serdes device for now */
   7430         /* coverity[overrun-local] */
   7431         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   7432             if (port_diag_ctrl(unit, port, PHY_DIAG_INT,
   7433                                       PHY_DIAG_CTRL_CMD, cmd,
   7434                                       &par) != SOC_E_NONE) {
   7435                 rv = CMD_FAIL;
   7436             }
   7437         }
   7438     } else if (sal_strcasecmp(cmd_str, "poke") == 0) {
   7439         cmd = PHY_DIAG_CTRL_POKE;
   7440         parse_table_init(unit, &pt);
   7441         parse_table_add(&pt, "fb", PQ_DFL | PQ_INT, (void *)(0), pData++, NULL);
   7442         parse_table_add(&pt, "val", PQ_DFL | PQ_INT, (void *)(0),
   7443                         pData++, NULL);
   7444         if (parse_arg_eq(args, &pt) < 0) {
   7445             cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   7446             parse_arg_eq_done(&pt);
   7447             return CMD_USAGE;
   7448         }
   7449         /* command targets to Internal serdes device for now */
   7450         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   7451             if (port_diag_ctrl(unit, port, PHY_DIAG_INT,
   7452                                       PHY_DIAG_CTRL_CMD, cmd,
   7453                                       &par) != SOC_E_NONE) {
   7454                 rv = CMD_FAIL;
   7455             }
   7456         }
   7457     } else if (sal_strcasecmp(cmd_str, "load_uc") == 0) {
   7458         cmd = PHY_DIAG_CTRL_LOAD_UC;
   7459         parse_table_init(unit, &pt);
   7460         parse_table_add(&pt, "crc", PQ_DFL | PQ_INT, (void *)(0),
   7461                         pData++, NULL);
   7462         parse_table_add(&pt, "debug", PQ_DFL | PQ_INT, (void *)(0),
   7463                         pData++, NULL);
   7464         if (parse_arg_eq(args, &pt) < 0) {
   7465             cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   7466             parse_arg_eq_done(&pt);
   7467             return CMD_USAGE;
   7468         }
   7469         /* command targets to Internal serdes device for now */
   7470         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   7471             if (port_diag_ctrl(unit, port, PHY_DIAG_INT,
   7472                                       PHY_DIAG_CTRL_CMD, cmd,
   7473                                       &par) != SOC_E_NONE) {
   7474                 rv = CMD_FAIL;
   7475             }
   7476         }
   7477     } else if (sal_strcasecmp(cmd_str, "veye") == 0) {
   7478         cmd = PHY_DIAG_CTRL_EYE_MARGIN_VEYE;
   7479         parse_table_init(unit, &pt);
   7480         parse_table_add(&pt, "live", PQ_DFL | PQ_INT, (void *)(0),
   7481                         pData++, NULL);
   7482         parse_table_add(&pt, "BER", PQ_DFL | PQ_INT, (void *)(0),
   7483                         pData++, NULL);
   7484         parse_table_add(&pt, "range", PQ_DFL | PQ_INT, (void *)(0),
   7485                         pData++, NULL);
   7486         parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0),
   7487                         pData++, NULL);
   7488         parse_table_add(&pt, "time_upper_bound", PQ_DFL | PQ_INT, (void *)(0),
   7489                         pData, NULL);
   7490         if (parse_arg_eq(args, &pt) < 0) {
   7491             cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   7492             parse_arg_eq_done(&pt);
   7493             return CMD_USAGE;
   7494         }
   7495         /* command targets to Internal serdes device for now */
   7496         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   7497             if (port_diag_ctrl(unit, port, PHY_DIAG_INT,
   7498                                       PHY_DIAG_CTRL_CMD, cmd,
   7499                                       &par) != SOC_E_NONE) {
   7500                 rv = CMD_FAIL;
   7501             }
   7502         }
   7503     } else if (sal_strcasecmp(cmd_str, "veye_u") == 0) {
   7504         cmd = PHY_DIAG_CTRL_EYE_MARGIN_VEYE_UP;
   7505         parse_table_init(unit, &pt);
   7506         parse_table_add(&pt, "live", PQ_DFL | PQ_INT, (void *)(0),
   7507                         pData++, NULL);
   7508         parse_table_add(&pt, "BER", PQ_DFL | PQ_INT, (void *)(0),
   7509                         pData++, NULL);
   7510         parse_table_add(&pt, "range", PQ_DFL | PQ_INT, (void *)(0),
   7511                         pData++, NULL);
   7512         parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0),
   7513                         pData++, NULL);
   7514         parse_table_add(&pt, "time_upper_bound", PQ_DFL | PQ_INT, (void *)(0),
   7515                         pData, NULL);
   7516         if (parse_arg_eq(args, &pt) < 0) {
   7517             cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   7518             parse_arg_eq_done(&pt);
   7519             return CMD_USAGE;
   7520         }
   7521         /* command targets to Internal serdes device for now */
   7522         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   7523             if (port_diag_ctrl(unit, port, PHY_DIAG_INT,
   7524                                       PHY_DIAG_CTRL_CMD, cmd,
   7525                                       &par) != SOC_E_NONE) {
   7526                 rv = CMD_FAIL;
   7527             }
   7528         }
   7529     } else if (sal_strcasecmp(cmd_str, "veye_d") == 0) {
   7530         cmd = PHY_DIAG_CTRL_EYE_MARGIN_VEYE_DOWN;
   7531         parse_table_init(unit, &pt);
   7532         parse_table_add(&pt, "live", PQ_DFL | PQ_INT, (void *)(0),
   7533                         pData++, NULL);
   7534         parse_table_add(&pt, "BER", PQ_DFL | PQ_INT, (void *)(0),
   7535                         pData++, NULL);
   7536         parse_table_add(&pt, "range", PQ_DFL | PQ_INT, (void *)(0),
   7537                         pData, NULL);
   7538         if (parse_arg_eq(args, &pt) < 0) {
   7539             cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   7540             parse_arg_eq_done(&pt);
   7541             return CMD_USAGE;
   7542         }
   7543         /* command targets to Internal serdes device for now */
   7544         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   7545             if (port_diag_ctrl(unit, port, PHY_DIAG_INT,
   7546                                       PHY_DIAG_CTRL_CMD, cmd,
   7547                                       &par) != SOC_E_NONE) {
   7548                 rv = CMD_FAIL;
   7549             }
   7550         }
   7551     } else if (sal_strcasecmp(cmd_str, "heye_r") == 0) {
   7552         cmd = PHY_DIAG_CTRL_EYE_MARGIN_HEYE_RIGHT;
   7553         parse_table_init(unit, &pt);
   7554         parse_table_add(&pt, "live", PQ_DFL | PQ_INT, (void *)(0),
   7555                         pData++, NULL);
   7556         parse_table_add(&pt, "BER", PQ_DFL | PQ_INT, (void *)(0),
   7557                         pData++, NULL);
   7558         parse_table_add(&pt, "range", PQ_DFL | PQ_INT, (void *)(0),
   7559                         pData++, NULL);
   7560         parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0),
   7561                         pData++, NULL);
   7562         parse_table_add(&pt, "time_upper_bound", PQ_DFL | PQ_INT, (void *)(0),
   7563                         pData, NULL);
   7564         if (parse_arg_eq(args, &pt) < 0) {
   7565             cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   7566             parse_arg_eq_done(&pt);
   7567             return CMD_USAGE;
   7568         }
   7569         /* command targets to Internal serdes device for now */
   7570         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   7571             if (port_diag_ctrl(unit, port, PHY_DIAG_INT,
   7572                                       PHY_DIAG_CTRL_CMD, cmd,
   7573                                       &par) != SOC_E_NONE) {
   7574                 rv = CMD_FAIL;
   7575             }
   7576         }
   7577     } else if (sal_strcasecmp(cmd_str, "heye_l") == 0) {
   7578         cmd = PHY_DIAG_CTRL_EYE_MARGIN_HEYE_LEFT;
   7579         parse_table_init(unit, &pt);
   7580         parse_table_add(&pt, "live", PQ_DFL | PQ_INT, (void *)(0),
   7581                         pData++, NULL);
   7582         parse_table_add(&pt, "BER", PQ_DFL | PQ_INT, (void *)(0),
   7583                         pData++, NULL);
   7584         parse_table_add(&pt, "range", PQ_DFL | PQ_INT, (void *)(0),
   7585                         pData++, NULL);
   7586         parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0),
   7587                         pData++, NULL);
   7588         parse_table_add(&pt, "time_upper_bound", PQ_DFL | PQ_INT, (void *)(0),
   7589                         pData, NULL);
   7590         if (parse_arg_eq(args, &pt) < 0) {
   7591             cli_out("Error: invalid option: %s\n", ARG_CUR(args));
   7592             parse_arg_eq_done(&pt);
   7593             return CMD_USAGE;
   7594         }
   7595         /* command targets to Internal serdes device for now */
   7596         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   7597             if (port_diag_ctrl(unit, port, PHY_DIAG_INT,
   7598                                       PHY_DIAG_CTRL_CMD, cmd,
   7599                                       &par) != SOC_E_NONE) {
   7600                 rv = CMD_FAIL;
   7601             }
   7602         }
   7603 
   7604     } else if (sal_strcasecmp(cmd_str, "dsc") == 0) {
   7605         rv = _phy_diag_dsc(unit, pbmp, args);
   7606     } else if (sal_strcasecmp(cmd_str, "pcs") == 0) {
   7607         rv = _phy_diag_pcs(unit, pbmp, args);
   7608     } else if (sal_strcasecmp(cmd_str, "reg") == 0) {
   7609         rv = _phy_diag_reg(unit, pbmp, args);
   7610     } else if (sal_strcasecmp(cmd_str, "eyescan") == 0) {
   7611         rv = _phy_diag_eyescan(unit, pbmp, args);
   7612     } else if (sal_strcasecmp(cmd_str, "LoopBack") == 0) {
   7613         rv = _phy_diag_loopback(unit, pbmp, args);
   7614 #ifdef BCM_TOMAHAWK3_SUPPORT
   7615     } else if (sal_strcasecmp(cmd_str, "prbsstat") == 0) {
   7616         rv = _phy_diag_prbsstat(unit, pbmp, args);
   7617     } else if (sal_strcasecmp(cmd_str, "fecstat") == 0) {
   7618         rv = _phy_diag_fecstat(unit, pbmp, args);
   7619 #endif /* BCM_TOMAHAWK3_SUPPORT */
   7620     } else if (sal_strcasecmp(cmd_str, "prbs") == 0) {
   7621         rv = _phy_diag_prbs(unit, pbmp, args);
   7622     } else if (sal_strcasecmp(cmd_str, "mfg") == 0) {
   7623         rv = _phy_diag_mfg(unit, pbmp, args);
   7624     } else if (sal_strcasecmp(cmd_str, "state") == 0) {
   7625         rv = _phy_diag_state(unit, pbmp, args);
   7626     } else if (sal_strcasecmp(cmd_str, "feyescan") == 0) {
   7627         rv = _phy_diag_fast_eyescan(unit, pbmp, args);
   7628     } else if (sal_strcasecmp(cmd_str, "linkmon") == 0) {
   7629         rv = _phy_diag_link_mon(unit, pbmp, args);
   7630     } else if (sal_strcasecmp(cmd_str, "berproj") == 0) {
   7631         rv = _phy_diag_berproj(unit, pbmp, args);
   7632 #ifdef PHYMOD_LINKCAT_SUPPORT
   7633     } else if (sal_strcasecmp(cmd_str, "linkcat") == 0) {
   7634         rv = _phy_diag_linkcat(unit, pbmp, args);
   7635 #endif /* PHYMOD_LINKCAT_SUPPORT */
   7636     }
   7637 
   7638 #ifdef SW_AUTONEG_SUPPORT
   7639     else if (sal_strcasecmp(cmd_str, "sw_an") == 0) {
   7640        
   7641         if (soc_feature(unit, soc_feature_sw_autoneg)) {
   7642             
   7643             DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
   7644                 if (bcm_sw_an_port_diag(unit, port)) {
   7645                     rv = CMD_FAIL;
   7646                 }
   7647             }
   7648         } else {
   7649             cli_out("Error: SW AUTONEG Not supported on this platform: \n");
   7650             rv = CMD_FAIL;
   7651         }           
   7652     } 
   7653 #endif
   7654     else {
   7655         cli_out("Error: unrecognized PHY DIAG command: %s\n", cmd_str);
   7656         rv = CMD_FAIL;
   7657     }
   7658 
   7659     if (lscan_time != 0) {
   7660         BCM_PBMP_ITER(pbmp, p) {
   7661             BCM_IF_ERROR_RETURN(bcm_linkscan_mode_set(unit, p, lnk_mode[p]));
   7662         }
   7663     }
   7664 
   7665     return rv;
   7666 }
   7667 
   7668 
   7669 STATIC cmd_result_t
   7670 _if_esw_phy_longreach(int u, args_t *a)
   7671 {
   7672     soc_pbmp_t pbm;
   7673     soc_port_t p, dport;
   7674     char *c;
   7675     int i;
   7676     cmd_result_t cmd_rv;
   7677     parse_table_t pt;
   7678     int print_header;
   7679     uint32 flags;
   7680     uint32 longreach_speed, longreach_pairs;
   7681     uint32 longreach_gain, longreach_autoneg;
   7682     uint32 longreach_local_ability, longreach_remote_ability;
   7683     uint32 longreach_current_ability, longreach_master;
   7684     uint32 longreach_active, longreach_enable;
   7685 
   7686     if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) {
   7687         cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c);
   7688         return CMD_FAIL;
   7689     }
   7690 
   7691     {
   7692 
   7693         if (c[0] == '=') {
   7694             return CMD_USAGE;       /* '=' unsupported */
   7695         }
   7696 
   7697         parse_table_init(u, &pt);
   7698 
   7699         parse_table_add(&pt, "SPeed", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT,
   7700                         0, &longreach_speed, 0);
   7701         parse_table_add(&pt, "PAirs", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT,
   7702                         0, &longreach_pairs, 0);
   7703         parse_table_add(&pt, "GAin", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT,
   7704                         0, &longreach_gain, 0);
   7705         parse_table_add(&pt, "AutoNeg", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   7706                         0, &longreach_autoneg, 0);
   7707         parse_table_add(&pt, "LocalAbility",
   7708                         PQ_LR_PHYAB | PQ_DFL | PQ_NO_EQ_OPT, 0,
   7709                         &longreach_local_ability, 0);
   7710         parse_table_add(&pt, "RemoteAbility",
   7711                         PQ_LR_PHYAB | PQ_DFL | PQ_NO_EQ_OPT, 0,
   7712                         &longreach_remote_ability, 0);
   7713         parse_table_add(&pt, "CurrentAbility",
   7714                         PQ_LR_PHYAB | PQ_DFL | PQ_NO_EQ_OPT, 0,
   7715                         &longreach_current_ability, 0);
   7716         parse_table_add(&pt, "MAster", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 0,
   7717                         &longreach_master, 0);
   7718         parse_table_add(&pt, "Active", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 0,
   7719                         &longreach_active, 0);
   7720         parse_table_add(&pt, "ENable", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 0,
   7721                         &longreach_enable, 0);
   7722 
   7723         if (parse_arg_eq(a, &pt) < 0) {
   7724             parse_arg_eq_done(&pt);
   7725             return CMD_USAGE;
   7726         }
   7727         if (ARG_CNT(a) > 0) {
   7728             cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a));
   7729             parse_arg_eq_done(&pt);
   7730             return CMD_USAGE;
   7731         }
   7732 
   7733         flags = 0;
   7734 
   7735         for (i = 0; i < pt.pt_cnt; i++) {
   7736             if (pt.pt_entries[i].pq_type & PQ_PARSED) {
   7737                 flags |= (1 << (SOC_PHY_CONTROL_LONGREACH_SPEED + i));
   7738             }
   7739         }
   7740         /* free allocated memory from arg parsing */
   7741         parse_arg_eq_done(&pt);
   7742 
   7743         /* coverity[overrun-local] */
   7744         DPORT_BCM_PBMP_ITER(u, pbm, dport, p) {
   7745             print_header = FALSE;
   7746 
   7747             cli_out("\nCurrent Longreach settings of %s ->\n",
   7748                     BCM_PORT_NAME(u, p));
   7749 
   7750             /* Read and set the longreach speed */
   7751             cmd_rv = port_phy_control_update(u, p,
   7752                                              BCM_PORT_PHY_CONTROL_LONGREACH_SPEED,
   7753                                              longreach_speed,
   7754                                              flags, &print_header);
   7755             if (cmd_rv != CMD_OK) {
   7756                 return cmd_rv;
   7757             }
   7758 
   7759             /* Read and set the longreach pairs */
   7760             cmd_rv = port_phy_control_update(u, p,
   7761                                              BCM_PORT_PHY_CONTROL_LONGREACH_PAIRS,
   7762                                              longreach_pairs,
   7763                                              flags, &print_header);
   7764             if (cmd_rv != CMD_OK) {
   7765                 return cmd_rv;
   7766             }
   7767 
   7768             /* Read and set the longreach gain */
   7769             cmd_rv = port_phy_control_update(u, p,
   7770                                              BCM_PORT_PHY_CONTROL_LONGREACH_GAIN,
   7771                                              longreach_gain,
   7772                                              flags, &print_header);
   7773             if (cmd_rv != CMD_OK) {
   7774                 return cmd_rv;
   7775             }
   7776 
   7777             /* Read and set the longreach autoneg (LDS) */
   7778             cmd_rv = port_phy_control_update(u, p,
   7779                                              BCM_PORT_PHY_CONTROL_LONGREACH_AUTONEG,
   7780                                              longreach_autoneg,
   7781                                              flags, &print_header);
   7782             if (cmd_rv != CMD_OK) {
   7783                 return cmd_rv;
   7784             }
   7785 
   7786             /* Read and set the longreach local ability */
   7787             cmd_rv = port_phy_control_update(u, p,
   7788                                              BCM_PORT_PHY_CONTROL_LONGREACH_LOCAL_ABILITY,
   7789                                              longreach_local_ability,
   7790                                              flags, &print_header);
   7791             if (cmd_rv != CMD_OK) {
   7792                 return cmd_rv;
   7793             }
   7794             /* Read the longreach remote ability */
   7795             cmd_rv = port_phy_control_update(u, p,
   7796                                              BCM_PORT_PHY_CONTROL_LONGREACH_REMOTE_ABILITY,
   7797                                              longreach_remote_ability,
   7798                                              flags, &print_header);
   7799             if (cmd_rv != CMD_OK) {
   7800                 return cmd_rv;
   7801             }
   7802 
   7803             /* Read the longreach current ability (GCD - read only) */
   7804             cmd_rv = port_phy_control_update(u, p,
   7805                                              BCM_PORT_PHY_CONTROL_LONGREACH_CURRENT_ABILITY,
   7806                                              longreach_current_ability,
   7807                                              flags, &print_header);
   7808             if (cmd_rv != CMD_OK) {
   7809                 return cmd_rv;
   7810             }
   7811 
   7812             /* Read and set the longreach master (when no LDS) */
   7813             cmd_rv = port_phy_control_update(u, p,
   7814                                              BCM_PORT_PHY_CONTROL_LONGREACH_MASTER,
   7815                                              longreach_master,
   7816                                              flags, &print_header);
   7817             if (cmd_rv != CMD_OK) {
   7818                 return cmd_rv;
   7819             }
   7820             /* Read and set the longreach active (LR is active - read only) */
   7821             cmd_rv = port_phy_control_update(u, p,
   7822                                              BCM_PORT_PHY_CONTROL_LONGREACH_ACTIVE,
   7823                                              longreach_active,
   7824                                              flags, &print_header);
   7825             if (cmd_rv != CMD_OK) {
   7826                 return cmd_rv;
   7827             }
   7828             /* Read and set the longreach active (Enable LR) */
   7829             cmd_rv = port_phy_control_update(u, p,
   7830                                              BCM_PORT_PHY_CONTROL_LONGREACH_ENABLE,
   7831                                              longreach_enable,
   7832                                              flags, &print_header);
   7833             if (cmd_rv != CMD_OK) {
   7834                 return cmd_rv;
   7835             }
   7836 
   7837         }
   7838 
   7839     }
   7840 
   7841     return CMD_OK;
   7842 }
   7843 
   7844 STATIC cmd_result_t
   7845 _if_esw_phy_extlb(int u, args_t *a)
   7846 {
   7847     soc_pbmp_t pbm;
   7848     soc_port_t p, dport;
   7849     char *c;
   7850     int i;
   7851     cmd_result_t cmd_rv;
   7852     parse_table_t pt;
   7853     int print_header;
   7854     uint32 flags;
   7855     uint32 enable;
   7856 
   7857     if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) {
   7858         cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c);
   7859         return CMD_FAIL;
   7860     }
   7861 
   7862     {
   7863 
   7864         if (c[0] == '=') {
   7865             return CMD_USAGE;       /* '=' unsupported */
   7866         }
   7867 
   7868         parse_table_init(u, &pt);
   7869 
   7870         parse_table_add(&pt, "ENable", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   7871                         0, &enable, 0);
   7872 
   7873         if (parse_arg_eq(a, &pt) < 0) {
   7874             parse_arg_eq_done(&pt);
   7875             return CMD_USAGE;
   7876         }
   7877 
   7878         if (ARG_CNT(a) > 0) {
   7879             cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a));
   7880             parse_arg_eq_done(&pt);
   7881             return CMD_USAGE;
   7882         }
   7883 
   7884         flags = 0;
   7885 
   7886         for (i = 0; i < pt.pt_cnt; i++) {
   7887             if (pt.pt_entries[i].pq_type & PQ_PARSED) {
   7888                 flags |= (1 << (SOC_PHY_CONTROL_LOOPBACK_EXTERNAL + i));
   7889             }
   7890         }
   7891         /* free allocated memory from arg parsing */
   7892         parse_arg_eq_done(&pt);
   7893 
   7894         /* coverity[overrun-local] */
   7895         DPORT_BCM_PBMP_ITER(u, pbm, dport, p) {
   7896             print_header = FALSE;
   7897 
   7898             cli_out("\nExternal loopback plug mode setting of %s ->\n",
   7899                     BCM_PORT_NAME(u, p));
   7900 
   7901             /* Get and set the external loopback plug mode */
   7902             cmd_rv = port_phy_control_update(u, p,
   7903                                              BCM_PORT_PHY_CONTROL_LOOPBACK_EXTERNAL,
   7904                                              enable, flags, &print_header);
   7905             if (cmd_rv != CMD_OK) {
   7906                 return cmd_rv;
   7907             }
   7908 
   7909         }
   7910 
   7911     }
   7912 
   7913     return CMD_OK;
   7914 }
   7915 
   7916 STATIC cmd_result_t
   7917 _if_esw_phy_clock(int u, args_t *a)
   7918 {
   7919     soc_pbmp_t pbm;
   7920     soc_port_t p, dport;
   7921     char *c;
   7922     int i;
   7923     cmd_result_t cmd_rv;
   7924     parse_table_t pt;
   7925     int print_header;
   7926     uint32 flags;
   7927     uint32 pri_enable, sec_enable, frequency, mode_auto, auto_sec, source, base, offset;
   7928 
   7929     if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) {
   7930         cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c);
   7931         return CMD_FAIL;
   7932     }
   7933 
   7934     {
   7935 
   7936         if (c[0] == '=') {
   7937             return CMD_USAGE;       /* '=' unsupported */
   7938         }
   7939 
   7940         parse_table_init(u, &pt);
   7941 
   7942         parse_table_add(&pt, "PRImary", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   7943                         0, &pri_enable, 0);
   7944         parse_table_add(&pt, "SECondary", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   7945                         0, &sec_enable, 0);
   7946         parse_table_add(&pt, "FRequency", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT,
   7947                         0, &frequency, 0);
   7948         parse_table_add(&pt, "AutoDisable", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   7949                         0, &mode_auto, 0);
   7950         parse_table_add(&pt, "AutoSECondary", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT,
   7951                         0, &auto_sec, 0);
   7952         parse_table_add(&pt, "ClockSource", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT,
   7953                         0, &source, 0);
   7954 
   7955         parse_table_add(&pt, "BAse", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT,
   7956                         0, &base, 0);
   7957         parse_table_add(&pt, "OFfset", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT,
   7958                         0, &offset, 0);
   7959 
   7960         if (parse_arg_eq(a, &pt) < 0) {
   7961             parse_arg_eq_done(&pt);
   7962             return CMD_USAGE;
   7963         }
   7964 
   7965         if (ARG_CNT(a) > 0) {
   7966             cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a));
   7967             parse_arg_eq_done(&pt);
   7968             return CMD_USAGE;
   7969         }
   7970 
   7971         flags = 0;
   7972 
   7973         for (i = 0; i < pt.pt_cnt; i++) {
   7974             if (pt.pt_entries[i].pq_type & PQ_PARSED) {
   7975                 /* flags |= (1 << (SOC_PHY_CONTROL_CLOCK_ENABLE + i)); */
   7976                 flags |= (1 << i);
   7977             }
   7978         }
   7979         /* free allocated memory from arg parsing */
   7980         parse_arg_eq_done(&pt);
   7981 
   7982         /* coverity[overrun-local] */
   7983         DPORT_BCM_PBMP_ITER(u, pbm, dport, p) {
   7984             print_header = FALSE;
   7985 
   7986             cli_out("Clock extraction setting of %s ->\n",
   7987                     BCM_PORT_NAME(u, p));
   7988 
   7989             cmd_rv = port_phy_control_update(u, p,
   7990                                              BCM_PORT_PHY_CONTROL_CLOCK_ENABLE,
   7991                                              pri_enable,
   7992                                              flags, &print_header);
   7993             if (cmd_rv != CMD_OK) {
   7994                 return cmd_rv;
   7995             }
   7996             cmd_rv = port_phy_control_update(u, p,
   7997                                              BCM_PORT_PHY_CONTROL_CLOCK_SECONDARY_ENABLE,
   7998                                              sec_enable,
   7999                                              flags, &print_header);
   8000             if (cmd_rv != CMD_OK) {
   8001                 return cmd_rv;
   8002             }
   8003             cmd_rv = port_phy_control_update(u, p,
   8004                                              BCM_PORT_PHY_CONTROL_CLOCK_FREQUENCY,
   8005                                              frequency,
   8006                                              flags, &print_header);
   8007             if (cmd_rv != CMD_OK) {
   8008                 return cmd_rv;
   8009             }
   8010             cmd_rv = port_phy_control_update(u, p,
   8011                                              BCM_PORT_PHY_CONTROL_CLOCK_MODE_AUTO,
   8012                                              mode_auto,
   8013                                              flags, &print_header);
   8014             if (cmd_rv != CMD_OK) {
   8015                 return cmd_rv;
   8016             }
   8017             cmd_rv = port_phy_control_update(u, p,
   8018                                              BCM_PORT_PHY_CONTROL_CLOCK_AUTO_SECONDARY,
   8019                                              auto_sec,
   8020                                              flags, &print_header);
   8021             if (cmd_rv != CMD_OK) {
   8022                 return cmd_rv;
   8023             }
   8024             cmd_rv = port_phy_control_update(u, p,
   8025                                              BCM_PORT_PHY_CONTROL_CLOCK_SOURCE,
   8026                                              source,
   8027                                              flags, &print_header);
   8028             if (cmd_rv != CMD_OK) {
   8029                 return cmd_rv;
   8030             }
   8031             cmd_rv = port_phy_control_update(u, p,
   8032                                              BCM_PORT_PHY_CONTROL_PORT_PRIMARY,
   8033                                              base, flags, &print_header);
   8034             if (cmd_rv != CMD_OK) {
   8035                 return cmd_rv;
   8036             }
   8037             cmd_rv = port_phy_control_update(u, p,
   8038                                              BCM_PORT_PHY_CONTROL_PORT_OFFSET,
   8039                                              offset, flags, &print_header);
   8040             if (cmd_rv != CMD_OK) {
   8041                 return cmd_rv;
   8042             }
   8043         } /* DPORT_BCM_PBMP_ITER( ) */
   8044     }
   8045     return CMD_OK;
   8046 }
   8047 
   8048 STATIC cmd_result_t
   8049 _if_esw_phy_wr(int u, args_t *a)
   8050 {
   8051     char *c;
   8052     cmd_result_t cmd_rv;
   8053     bcm_port_t port;
   8054     uint32 block;
   8055     uint32 address;
   8056     uint32 value;
   8057 
   8058     /* Get port */
   8059     if ((c = ARG_GET(a)) == NULL) {
   8060         return CMD_USAGE;
   8061     }
   8062     port = sal_ctoi(c, 0);
   8063     if (!SOC_PORT_VALID(u, port)) {
   8064         cli_out("%s: Invalid port\n", ARG_CMD(a));
   8065         return CMD_FAIL;
   8066     }
   8067 
   8068     /* Get block */
   8069     if ((c = ARG_GET(a)) == NULL) {
   8070         return CMD_USAGE;
   8071     }
   8072     block = sal_ctoi(c, 0);
   8073 
   8074     /* Get address */
   8075     if ((c = ARG_GET(a)) == NULL) {
   8076         return CMD_USAGE;
   8077     }
   8078     address = sal_ctoi(c, 0);
   8079 
   8080     /* Get value */
   8081     if ((c = ARG_GET(a)) == NULL) {
   8082         return CMD_USAGE;
   8083     }
   8084     value = sal_ctoi(c, 0);
   8085 
   8086     /* Write the phy register */
   8087     cmd_rv = bcm_port_phy_set(u, port, BCM_PORT_PHY_INTERNAL,
   8088                               BCM_PORT_PHY_REG_INDIRECT_ADDR
   8089                               (0, block, address), value);
   8090     return cmd_rv;
   8091 }
   8092 
   8093 STATIC cmd_result_t
   8094 _if_esw_phy_rd_cp(int u, args_t *a)
   8095 {
   8096     char *c;
   8097     cmd_result_t cmd_rv;
   8098     bcm_port_t port;
   8099     uint32 block;
   8100     uint32 address;
   8101     uint32 value;
   8102     uint32 rval;
   8103 
   8104     /* Get port */
   8105     c = ARG_GET(a);
   8106     port = sal_ctoi(c, 0);
   8107     if (!SOC_PORT_VALID(u, port)) {
   8108         cli_out("%s: Invalid port\n", ARG_CMD(a));
   8109         return CMD_FAIL;
   8110     }
   8111 
   8112     /* Get block */
   8113     if ((c = ARG_GET(a)) == NULL) {
   8114         return CMD_USAGE;
   8115     }
   8116     block = sal_ctoi(c, 0);
   8117 
   8118     /* Get address */
   8119     if ((c = ARG_GET(a)) == NULL) {
   8120         return CMD_USAGE;
   8121     }
   8122     address = sal_ctoi(c, 0);
   8123 
   8124     /* Get compare value */
   8125     if ((c = ARG_GET(a)) == NULL) {
   8126         return CMD_USAGE;
   8127     }
   8128     value = sal_ctoi(c, 0);
   8129 
   8130     /* Read the phy register */
   8131     cmd_rv = bcm_port_phy_get(u, port, BCM_PORT_PHY_INTERNAL,
   8132                               BCM_PORT_PHY_REG_INDIRECT_ADDR
   8133                               (0, block, address), &rval);
   8134 
   8135     if (value != rval) {
   8136         cli_out("Error: block %x, register %x expected %x, got %x\n",
   8137                 block, address, value, rval);
   8138     } else {
   8139         cli_out("Pass\n");
   8140     }
   8141     return cmd_rv;
   8142 }
   8143 
   8144 STATIC cmd_result_t
   8145 _if_esw_phy_rd_cp2(int u, args_t *a)
   8146 {
   8147     char *c;
   8148     cmd_result_t cmd_rv;
   8149     bcm_port_t port;
   8150     uint32 block;
   8151     uint32 address;
   8152     uint32 value;
   8153     uint32 mask;
   8154     uint32 rval;
   8155 
   8156     /* Get port */
   8157     c = ARG_GET(a);
   8158     port = sal_ctoi(c, 0);
   8159     if (!SOC_PORT_VALID(u, port)) {
   8160         cli_out("%s: Invalid port\n", ARG_CMD(a));
   8161         return CMD_FAIL;
   8162     }
   8163 
   8164     /* Get block */
   8165     if ((c = ARG_GET(a)) == NULL) {
   8166         return CMD_USAGE;
   8167     }
   8168     block = sal_ctoi(c, 0);
   8169 
   8170     /* Get address */
   8171     if ((c = ARG_GET(a)) == NULL) {
   8172         return CMD_USAGE;
   8173     }
   8174     address = sal_ctoi(c, 0);
   8175 
   8176     /* Get compare value */
   8177     if ((c = ARG_GET(a)) == NULL) {
   8178         return CMD_USAGE;
   8179     }
   8180     value = sal_ctoi(c, 0);
   8181 
   8182     /* Get mask */
   8183     if ((c = ARG_GET(a)) == NULL) {
   8184         return CMD_USAGE;
   8185     }
   8186     mask = sal_ctoi(c, 0);
   8187 
   8188     /* Read the phy register */
   8189     cmd_rv = bcm_port_phy_get(u, port, BCM_PORT_PHY_INTERNAL,
   8190                               BCM_PORT_PHY_REG_INDIRECT_ADDR
   8191                               (0, block, address), &rval);
   8192 
   8193     if ((value & mask) != (rval & mask)) {
   8194         cli_out("Error: block %x, register %x expected %x, got %x\n",
   8195                 block, address, (value & mask), (rval & mask));
   8196     } else {
   8197         cli_out("Pass\n");
   8198     }
   8199     return cmd_rv;
   8200 }
   8201 
   8202 STATIC cmd_result_t
   8203 _if_esw_phy_mod(int u, args_t *a)
   8204 {
   8205     char *c;
   8206     cmd_result_t cmd_rv;
   8207     bcm_port_t port;
   8208     int block;
   8209     uint32 flags;
   8210     uint32 address;
   8211     uint32 value;
   8212     uint32 mask;
   8213 
   8214     /* Get port */
   8215     if ((c = ARG_GET(a)) == NULL) {
   8216         return CMD_USAGE;
   8217     }
   8218     port = sal_ctoi(c, 0);
   8219     if (!SOC_PORT_VALID(u, port)) {
   8220         cli_out("%s: Invalid port\n", ARG_CMD(a));
   8221         return CMD_FAIL;
   8222     }
   8223 
   8224     /* Get block */
   8225     if ((c = ARG_GET(a)) == NULL) {
   8226         return CMD_USAGE;
   8227     }
   8228     block = sal_ctoi(c, 0);
   8229 
   8230     /* Get address */
   8231     if ((c = ARG_GET(a)) == NULL) {
   8232         return CMD_USAGE;
   8233     }
   8234     address = sal_ctoi(c, 0);
   8235 
   8236     /* Get value */
   8237     if ((c = ARG_GET(a)) == NULL) {
   8238         return CMD_USAGE;
   8239     }
   8240     value = sal_ctoi(c, 0);
   8241 
   8242     /* Get mask */
   8243     if ((c = ARG_GET(a)) == NULL) {
   8244         return CMD_USAGE;
   8245     }
   8246     mask = sal_ctoi(c, 0);
   8247 
   8248     /* Modify the phy register */
   8249     flags = 0;
   8250     if (block >= 0) {
   8251         flags = BCM_PORT_PHY_INTERNAL;
   8252         address = BCM_PORT_PHY_REG_INDIRECT_ADDR(0, block, address);
   8253     }
   8254     cmd_rv = bcm_port_phy_modify(u, port, flags, address, value, mask);
   8255 
   8256     return cmd_rv;
   8257 }
   8258 
   8259 STATIC cmd_result_t
   8260 _if_esw_phy_control(int u, args_t *a)
   8261 {
   8262     soc_pbmp_t pbm;
   8263     soc_port_t p, dport;
   8264     char *c;
   8265     uint32 wan_mode, preemphasis, predriver_current, driver_current, dfe, lp_dfe, br_dfe, linkTraining;
   8266     uint32 sw_rx_los_nval = 0, sw_rx_los_oval;
   8267     uint32 eq_boost;
   8268     uint32 interface;
   8269     uint32 interfacemax;
   8270     uint32 flags;
   8271     int print_header;
   8272     cmd_result_t cmd_rv;
   8273     bcm_error_t bcm_rv;
   8274     bcm_port_config_t pcfg;
   8275     int eq_tune = FALSE;
   8276     int eq_status = FALSE;
   8277     int dump = FALSE;
   8278     int farEndEqValue = 0;
   8279 #ifdef INCLUDE_MACSEC
   8280     uint32 macsec_switch_fixed, macsec_switch_fixed_speed;
   8281     uint32 macsec_switch_fixed_duplex, macsec_switch_fixed_pause;
   8282     uint32 macsec_pause_rx_fwd, macsec_pause_tx_fwd;
   8283     uint32 macsec_line_ipg, macsec_switch_ipg;
   8284 
   8285     macsec_switch_fixed = 0;
   8286     macsec_switch_fixed_speed = 0;
   8287     macsec_switch_fixed_duplex = 0;
   8288     macsec_switch_fixed_pause = 0;
   8289     macsec_pause_rx_fwd = 0;
   8290     macsec_pause_tx_fwd = 0;
   8291     macsec_line_ipg = 0;
   8292     macsec_switch_ipg = 0;
   8293 #endif
   8294 
   8295     if (bcm_port_config_get(u, &pcfg) != BCM_E_NONE) {
   8296         cli_out("%s: Error: bcm ports not initialized\n", ARG_CMD(a));
   8297         return CMD_FAIL;
   8298     }
   8299 
   8300     wan_mode = 0;
   8301     preemphasis = 0;
   8302     predriver_current = 0;
   8303     driver_current = 0;
   8304     interface = 0;
   8305     interfacemax = 0;
   8306     eq_boost = 0;
   8307 
   8308     dfe = 0;
   8309     lp_dfe = 0;
   8310     br_dfe = 0;
   8311     linkTraining = 0;
   8312 
   8313     if ((c = ARG_GET(a)) == NULL) {
   8314         SOC_PBMP_ASSIGN(pbm, pcfg.port);
   8315     } else if (parse_bcm_pbmp(u, c, &pbm) < 0) {
   8316         cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c);
   8317         return CMD_FAIL;
   8318     }
   8319 
   8320     BCM_PBMP_AND(pbm, pcfg.port);
   8321 
   8322     flags = 0;
   8323     if ((c = ARG_CUR(a)) != NULL) {
   8324         parse_table_t pt;
   8325         int i;
   8326 
   8327         if (c[0] == '=') {
   8328             return CMD_USAGE;       /* '=' unsupported */
   8329         }
   8330         if (sal_strcasecmp(c, "RxTune") == 0) {
   8331             if (ARG_CNT(a) <= 1) { /*Current counter is at RxTune */
   8332                 ARG_NEXT(a);
   8333                 farEndEqValue = 0;
   8334                 cli_out("far end equalization value not input, using 0\n");
   8335             } else {
   8336                 /* go to next argument */
   8337                 ARG_NEXT(a);
   8338                 /* Get far end equalization value  */
   8339                 if ((c = ARG_GET(a)) != NULL) {
   8340                     farEndEqValue = sal_ctoi(c, 0);
   8341                     cli_out("far end equalization value input (%d)\n",
   8342                               farEndEqValue);
   8343                 }
   8344             }
   8345             eq_tune = TRUE;
   8346         }
   8347         if (sal_strcasecmp(c, "Dump") == 0) {
   8348             c = ARG_GET(a);
   8349             dump = TRUE;
   8350         }
   8351 
   8352         if ((eq_tune == FALSE) && (dump == FALSE)) {
   8353             parse_table_init(u, &pt);
   8354             parse_table_add(&pt, "WanMode", PQ_DFL | PQ_BOOL,
   8355                             0, &wan_mode, 0);
   8356             parse_table_add(&pt, "Preemphasis", PQ_DFL | PQ_INT,
   8357                             0, &preemphasis, 0);
   8358             parse_table_add(&pt, "DriverCurrent", PQ_DFL | PQ_INT,
   8359                             0, &driver_current, 0);
   8360             parse_table_add(&pt, "PreDriverCurrent", PQ_DFL | PQ_INT,
   8361                             0, &predriver_current, 0);
   8362             parse_table_add(&pt, "EqualizerBoost", PQ_DFL | PQ_INT,
   8363                             0, &eq_boost, 0);
   8364             parse_table_add(&pt, "Interface", PQ_DFL | PQ_INT,
   8365                             0, &interface, 0);
   8366             parse_table_add(&pt, "InterfaceMax", PQ_DFL | PQ_INT,
   8367                             0, &interfacemax, 0);
   8368             parse_table_add(&pt, "SwRxLos", PQ_DFL | PQ_INT,
   8369                             0, &sw_rx_los_nval, 0);
   8370             parse_table_add(&pt, "Dfe", PQ_DFL | PQ_INT,
   8371                             0, &dfe, 0);
   8372             parse_table_add(&pt, "LpDfe", PQ_DFL | PQ_INT,
   8373                             0, &lp_dfe, 0);
   8374             parse_table_add(&pt, "BrDfe", PQ_DFL | PQ_INT,
   8375                             0, &br_dfe, 0);
   8376             parse_table_add(&pt, "LT", PQ_DFL | PQ_INT,
   8377                             0, &linkTraining, 0);
   8378 
   8379 #ifdef INCLUDE_MACSEC
   8380             parse_table_add(&pt, "MacsecSwitchFixed", PQ_DFL | PQ_BOOL,
   8381                             0, &macsec_switch_fixed, 0);
   8382             parse_table_add(&pt, "MacsecSwitchFixedSpeed", PQ_DFL | PQ_INT,
   8383                             0, &macsec_switch_fixed_speed, 0);
   8384             parse_table_add(&pt, "MacsecSwitchFixedDuplex",
   8385                             PQ_DFL | PQ_BOOL, 0,
   8386                             &macsec_switch_fixed_duplex, 0);
   8387             parse_table_add(&pt, "MacsecSwitchFixedPause", PQ_DFL | PQ_BOOL,
   8388                             0, &macsec_switch_fixed_pause, 0);
   8389             parse_table_add(&pt, "MacsecPauseRXForward", PQ_DFL | PQ_BOOL,
   8390                             0, &macsec_pause_rx_fwd, 0);
   8391             parse_table_add(&pt, "MacsecPauseTXForward", PQ_DFL | PQ_BOOL,
   8392                             0, &macsec_pause_tx_fwd, 0);
   8393             parse_table_add(&pt, "MacsecLineIPG", PQ_DFL | PQ_INT, 0,
   8394                             &macsec_line_ipg, 0);
   8395             parse_table_add(&pt, "MacsecSwitchIPG", PQ_DFL | PQ_INT, 0,
   8396                             &macsec_switch_ipg, 0);
   8397 #endif
   8398 
   8399             if (parse_arg_eq(a, &pt) < 0) {
   8400                 parse_arg_eq_done(&pt);
   8401                 return CMD_USAGE;
   8402             }
   8403             if (ARG_CNT(a) > 0) {
   8404                 cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a));
   8405                 parse_arg_eq_done(&pt);
   8406                 return CMD_USAGE;
   8407             }
   8408 
   8409             for (i = 0; i < pt.pt_cnt; i++) {
   8410                 if (pt.pt_entries[i].pq_type & PQ_PARSED) {
   8411                     flags |= (1 << i);
   8412                 }
   8413             }
   8414             parse_arg_eq_done(&pt);
   8415         }
   8416     }
   8417     /* coverity[overrun-local] */
   8418     DPORT_BCM_PBMP_ITER(u, pbm, dport, p) {
   8419         print_header = TRUE;
   8420 
   8421         if (eq_tune == TRUE) {
   8422 
   8423             cmd_rv =
   8424                 bcm_port_control_set(u, p,
   8425                                      bcmPortControlSerdesDriverEqualizationFarEnd,
   8426                                      farEndEqValue);
   8427 
   8428             cmd_rv = bcm_port_control_set(u, p,
   8429                                           bcmPortControlSerdesDriverTune,
   8430                                           1);
   8431             if (cmd_rv != CMD_OK) {
   8432                 cli_out("unit %d port %d Tuning function not available\n",
   8433                         u, p);
   8434                 continue;
   8435             }
   8436             cli_out("Rx Equalization Tuning start\n");
   8437             sal_usleep(1000000);
   8438             cmd_rv = bcm_port_control_get(u, p,
   8439                                           bcmPortControlSerdesDriverEqualizationTuneStatusFarEnd,
   8440                                           &eq_status);
   8441 
   8442             cli_out("unit %d port %d Tuning done, Status: %s\n",
   8443                     u, p, ((cmd_rv == CMD_OK) && eq_status) ? "OK" : "FAIL");
   8444             continue;
   8445         }
   8446         if (dump == TRUE) {
   8447             /* coverity[returned_value] */
   8448             cmd_rv =
   8449                 bcm_port_phy_control_set(u, p, BCM_PORT_PHY_CONTROL_DUMP,
   8450                                          1);
   8451             continue;
   8452         }
   8453 
   8454         cmd_rv = port_phy_control_update(u, p, BCM_PORT_PHY_CONTROL_WAN,
   8455                                          wan_mode, flags, &print_header);
   8456         if (cmd_rv != CMD_OK) {
   8457             return cmd_rv;
   8458         }
   8459 
   8460         /* Read and set WAN mode */
   8461         cmd_rv = port_phy_control_update(u, p, BCM_PORT_PHY_CONTROL_WAN,
   8462                                          wan_mode, flags, &print_header);
   8463         if (cmd_rv != CMD_OK) {
   8464             return cmd_rv;
   8465         }
   8466 
   8467         /* Read and set Preemphasis */
   8468         cmd_rv = port_phy_control_update(u, p,
   8469                                          BCM_PORT_PHY_CONTROL_PREEMPHASIS,
   8470                                          preemphasis, flags, &print_header);
   8471         if (cmd_rv != CMD_OK) {
   8472             return cmd_rv;
   8473         }
   8474 
   8475         /* Read and set Driver Current */
   8476         cmd_rv = port_phy_control_update(u, p,
   8477                                          BCM_PORT_PHY_CONTROL_DRIVER_CURRENT,
   8478                                          driver_current, flags,
   8479                                          &print_header);
   8480         if (cmd_rv != CMD_OK) {
   8481             return cmd_rv;
   8482         }
   8483 
   8484         /* Read and set Pre-driver Current */
   8485         cmd_rv = port_phy_control_update(u, p,
   8486                                          BCM_PORT_PHY_CONTROL_PRE_DRIVER_CURRENT,
   8487                                          predriver_current, flags,
   8488                                          &print_header);
   8489         if (cmd_rv != CMD_OK) {
   8490             return cmd_rv;
   8491         }
   8492 
   8493         /* Read and set DFE */
   8494         cmd_rv = port_phy_control_update(u, p,
   8495                                          BCM_PORT_PHY_CONTROL_FIRMWARE_DFE_ENABLE,
   8496                                          dfe, flags, &print_header);
   8497         if (cmd_rv != CMD_OK) {
   8498             return cmd_rv;
   8499         }
   8500 
   8501         /* Read and set LP_DFE */
   8502         cmd_rv = port_phy_control_update(u, p,
   8503                                          BCM_PORT_PHY_CONTROL_FIRMWARE_LP_DFE_ENABLE,
   8504                                          lp_dfe, flags, &print_header);
   8505         if (cmd_rv != CMD_OK) {
   8506             return cmd_rv;
   8507         }
   8508 
   8509         /* Read and set  BR_DFE */
   8510         cmd_rv = port_phy_control_update(u, p,
   8511                                          BCM_PORT_PHY_CONTROL_FIRMWARE_BR_DFE_ENABLE,
   8512                                          br_dfe, flags, &print_header);
   8513         if (cmd_rv != CMD_OK) {
   8514             return cmd_rv;
   8515         }
   8516 
   8517         /* Read and set forced cl72/93 */
   8518         cmd_rv = port_phy_control_update(u, p,
   8519                                          BCM_PORT_PHY_CONTROL_CL72,
   8520                                          linkTraining, flags, &print_header);
   8521         if (cmd_rv != CMD_OK) {
   8522             return cmd_rv;
   8523         }
   8524 
   8525         /* Read and set Equalizer Boost */
   8526         cmd_rv = port_phy_control_update(u, p,
   8527                                          BCM_PORT_PHY_CONTROL_EQUALIZER_BOOST,
   8528                                          eq_boost, flags, &print_header);
   8529         if (cmd_rv != CMD_OK) {
   8530             return cmd_rv;
   8531         }
   8532 
   8533         /* Read and set the interface */
   8534         cmd_rv = port_phy_control_update(u, p,
   8535                                          BCM_PORT_PHY_CONTROL_INTERFACE,
   8536                                          interface, flags, &print_header);
   8537         if (cmd_rv != CMD_OK) {
   8538             return cmd_rv;
   8539         }
   8540         /* Read and set(is noop) the interface */
   8541         cmd_rv = port_phy_control_update(u, p,
   8542                                          SOC_PHY_CONTROL_INTERFACE_MAX,
   8543                                          interfacemax, flags,
   8544                                          &print_header);
   8545         if (cmd_rv != CMD_OK) {
   8546             return cmd_rv;
   8547         }
   8548 
   8549         /* Read and set(is noop) the interface */
   8550         bcm_rv = bcm_port_phy_control_get(u, p,
   8551                                           BCM_PORT_PHY_CONTROL_SOFTWARE_RX_LOS,
   8552                                           &sw_rx_los_oval);
   8553         if (BCM_FAILURE(bcm_rv) && BCM_E_UNAVAIL != bcm_rv) {
   8554             cli_out("%s\n", bcm_errmsg(bcm_rv));
   8555             return CMD_FAIL;
   8556         } else if (BCM_SUCCESS(bcm_rv)) {
   8557             if ((sw_rx_los_nval != sw_rx_los_oval) && (flags & (1 << 7))) {
   8558                 bcm_rv = bcm_port_phy_control_set(u, p,
   8559                                                   BCM_PORT_PHY_CONTROL_SOFTWARE_RX_LOS,
   8560                                                   sw_rx_los_nval);
   8561                 if (BCM_FAILURE(bcm_rv)) {
   8562                     cli_out("%s\n", bcm_errmsg(bcm_rv));
   8563                     return CMD_FAIL;
   8564                 }
   8565                 sw_rx_los_oval = sw_rx_los_nval;
   8566             }
   8567             cmd_rv = CMD_OK;
   8568             cli_out("Rx LOS (s/w) enable         - %d\n", sw_rx_los_oval);
   8569         }
   8570 #ifdef INCLUDE_MACSEC
   8571 
   8572         /* Read and set the Switch fixed */
   8573         cmd_rv = port_phy_control_update(u, p,
   8574                                          BCM_PORT_PHY_CONTROL_MACSEC_SWITCH_FIXED,
   8575                                          macsec_switch_fixed,
   8576                                          flags, &print_header);
   8577         if (cmd_rv != CMD_OK) {
   8578             return cmd_rv;
   8579         }
   8580 
   8581         /* Read and set the Switch fixed Speed */
   8582         cmd_rv = port_phy_control_update(u, p,
   8583                                          BCM_PORT_PHY_CONTROL_MACSEC_SWITCH_FIXED_SPEED,
   8584                                          macsec_switch_fixed_speed,
   8585                                          flags, &print_header);
   8586         if (cmd_rv != CMD_OK) {
   8587             return cmd_rv;
   8588         }
   8589 
   8590         /* Read and set the Switch fixed Duplex */
   8591         cmd_rv = port_phy_control_update(u, p,
   8592                                          BCM_PORT_PHY_CONTROL_MACSEC_SWITCH_FIXED_DUPLEX,
   8593                                          macsec_switch_fixed_duplex,
   8594                                          flags, &print_header);
   8595         if (cmd_rv != CMD_OK) {
   8596             return cmd_rv;
   8597         }
   8598 
   8599         /* Read and set the Switch fixed Pause */
   8600         cmd_rv = port_phy_control_update(u, p,
   8601                                          BCM_PORT_PHY_CONTROL_MACSEC_SWITCH_FIXED_PAUSE,
   8602                                          macsec_switch_fixed_pause,
   8603                                          flags, &print_header);
   8604         if (cmd_rv != CMD_OK) {
   8605             return cmd_rv;
   8606         }
   8607 
   8608         /* Read and set Pause Receive Forward */
   8609         cmd_rv = port_phy_control_update(u, p,
   8610                                          BCM_PORT_PHY_CONTROL_MACSEC_PAUSE_RX_FORWARD,
   8611                                          macsec_pause_rx_fwd,
   8612                                          flags, &print_header);
   8613         if (cmd_rv != CMD_OK) {
   8614             return cmd_rv;
   8615         }
   8616 
   8617         /* Read and set Pause transmit Forward */
   8618         cmd_rv = port_phy_control_update(u, p,
   8619                                          BCM_PORT_PHY_CONTROL_MACSEC_PAUSE_TX_FORWARD,
   8620                                          macsec_pause_tx_fwd,
   8621                                          flags, &print_header);
   8622         if (cmd_rv != CMD_OK) {
   8623             return cmd_rv;
   8624         }
   8625 
   8626         /* Read and set Line Side IPG */
   8627         cmd_rv = port_phy_control_update(u, p,
   8628                                          BCM_PORT_PHY_CONTROL_MACSEC_LINE_IPG,
   8629                                          macsec_line_ipg,
   8630                                          flags, &print_header);
   8631         if (cmd_rv != CMD_OK) {
   8632             return cmd_rv;
   8633         }
   8634 
   8635         /* Read and set Switch Side IPG */
   8636         cmd_rv = port_phy_control_update(u, p,
   8637                                          BCM_PORT_PHY_CONTROL_MACSEC_SWITCH_IPG,
   8638                                          macsec_switch_ipg,
   8639                                          flags, &print_header);
   8640         if (cmd_rv != CMD_OK) {
   8641             return cmd_rv;
   8642         }
   8643 #endif
   8644     }
   8645     return CMD_OK;
   8646 }
   8647 
   8648 STATIC cmd_result_t
   8649 _if_esw_phy_dumpall(int u, args_t *a)
   8650 {
   8651     char *c;
   8652     uint16 phy_data, phy_devad = 0;
   8653     uint16 phy_addr;
   8654     uint32 phy_reg;
   8655     uint16 phy_addr_start = 0;
   8656     uint16 phy_addr_end = 0xFF;
   8657     int is_c45 = 0;
   8658     int rv = 0;
   8659 
   8660     if ((c = ARG_GET(a)) == NULL) {
   8661         cli_out("%s: Error: expecting \"c45\" or \"c22\"\n", ARG_CMD(a));
   8662         return CMD_USAGE;
   8663     }
   8664     is_c45 = 0;
   8665     if (sal_strcasecmp(c, "c45") == 0) {
   8666         is_c45 = 1;
   8667         if (!soc_feature(u, soc_feature_phy_cl45)) {
   8668             cli_out("%s: Error: Device does not support clause 45\n",
   8669                     ARG_CMD(a));
   8670             return CMD_USAGE;
   8671         }
   8672     } else if (sal_strcasecmp(c, "c22") != 0) {
   8673         cli_out("%s: Error: expecting \"c45\" or \"c22\"\n", ARG_CMD(a));
   8674         return CMD_USAGE;
   8675     }
   8676     if ((c = ARG_GET(a)) != NULL) {
   8677         char *end;
   8678 
   8679         phy_addr_start = sal_strtoul(c, &end, 0);
   8680         if (*end) {
   8681             cli_out("%s: Error: Expecting PHY start address [%s]\n",
   8682                     ARG_CMD(a), c);
   8683             return CMD_USAGE;
   8684         }
   8685         if ((c = ARG_GET(a)) != NULL) {
   8686             phy_addr_end = sal_strtoul(c, &end, 0);
   8687             if (*end) {
   8688                 cli_out("%s: Error: Expecting PHY end address [%s]\n",
   8689                         ARG_CMD(a), c);
   8690                 return CMD_USAGE;
   8691             }
   8692         } else {
   8693             /* If start specified but no end, just print one phy address */
   8694             phy_addr_end = phy_addr_start;
   8695         }
   8696     } else {
   8697         /* phy addr start and end are not specified */
   8698         if (SOC_IS_TRIDENT3(u) || SOC_IS_TOMAHAWK(u)) {
   8699             phy_addr_end = 0x1FF;
   8700         } else if (SOC_IS_TOMAHAWK3(u)) {
   8701             phy_addr_end = 0x2FF;
   8702         }
   8703     }
   8704 
   8705     if (is_c45) {
   8706         cli_out("%4s%5s %5s %3s: %-6s\n", "", "PRTAD", "DEVAD", "REG",
   8707                 "VALUE");
   8708         for (phy_addr = phy_addr_start; phy_addr <= phy_addr_end;
   8709              phy_addr++) {
   8710             /* Clause 45 supports 32 devices per phy. */
   8711             for (phy_devad = 0; phy_devad <= 0x1f; phy_devad++) {
   8712                 /* Device ID is in registers 2 and 3 */
   8713                 for (phy_reg = 2; phy_reg <= 3; phy_reg++) {
   8714                     rv = soc_miimc45_read(u, phy_addr, phy_devad,
   8715                                           phy_reg, &phy_data);
   8716                     if (rv < 0) {
   8717                         cli_out("ERROR: MII Addr %d: "
   8718                                 "soc_miim_read failed: %s\n",
   8719                                 phy_addr, soc_errmsg(rv));
   8720                         return CMD_FAIL;
   8721                     }
   8722                     /* Assume device doesn't exist in phy if 
   8723                        read back is all 0/1 */
   8724                     if ((phy_data != 0xFFFF) && (phy_data != 0x0000) && 
   8725                         (phy_data != 0x7FFF)&& (phy_data != 0x3FFF)) {
   8726                         cli_out("%4s 0x%02X 0x%02X 0x%02X: 0x%04X\n",
   8727                                 "", phy_addr, phy_devad, phy_reg, phy_data);
   8728                     }
   8729                 }
   8730             }
   8731         }
   8732     } else {
   8733         cli_out("%4s%5s %3s: %-6s\n", "", "PRTAD", "REG", "VALUE");
   8734         for (phy_addr = phy_addr_start; phy_addr <= phy_addr_end;
   8735              phy_addr++) {
   8736             /* Device ID is in registers 2 and 3 */
   8737             for (phy_reg = 2; phy_reg <= 3; phy_reg++) {
   8738                 rv = soc_miim_read(u, phy_addr, phy_reg, &phy_data);
   8739                 if (rv < 0) {
   8740                     cli_out("ERROR: MII Addr %d: soc_miim_read failed: %s\n",
   8741                             phy_addr, soc_errmsg(rv));
   8742                     return CMD_FAIL;
   8743                 }
   8744                 if ((phy_data != 0xFFFF) && (phy_data != 0x0000)) {
   8745                     cli_out("%4s0x%02X 0x%02x: 0x%04x\n",
   8746                             "", phy_addr, phy_reg, phy_data);
   8747                 }
   8748             }
   8749         }
   8750     }
   8751     return CMD_OK;
   8752 }
   8753 
   8754 STATIC cmd_result_t
   8755 _if_esw_phy_raw(int u, args_t *a)
   8756 {
   8757     char *c, *bus_name;
   8758     int is_c45 = 0;
   8759     int is_sbus = 0;
   8760     int is_sim = 0;
   8761     int is_mpp1 = 0;
   8762     uint16 phy_data, phy_devad = 0;
   8763     uint16 phy_addr, phy_lane = 0, phy_pindex = 0;
   8764     uint32 phy_reg, phy_wrmask;
   8765     uint32 phy_data32, phy_aer = 0;
   8766     int rv = 0;
   8767 
   8768     if ((c = ARG_GET(a)) == NULL) {
   8769         return CMD_USAGE;
   8770     }
   8771 
   8772     bus_name = "miim";
   8773     if (sal_strcasecmp(c, "sbus") == 0) {
   8774         is_sbus = 1;
   8775         bus_name = "sbus_mdio";
   8776         if ((c = ARG_GET(a)) == NULL) {
   8777             return CMD_USAGE;
   8778         }
   8779     } else if (sal_strcasecmp(c, "sim") == 0) {
   8780         is_sim = 1;
   8781         bus_name = "physim";
   8782         if ((c = ARG_GET(a)) == NULL) {
   8783             return CMD_USAGE;
   8784         }
   8785     } else if (soc_feature(u, soc_feature_phy_cl45)) {
   8786         if (sal_strcasecmp(c, "c45") == 0) {
   8787             bus_name = "miimc45";
   8788             is_c45 = 1;
   8789             if ((c = ARG_GET(a)) == NULL) {
   8790                 return CMD_USAGE;
   8791             }
   8792         }
   8793     }
   8794     phy_addr = sal_strtoul(c, NULL, 0);
   8795     if ((c = ARG_GET(a)) == NULL) { /* Get register number */
   8796         return CMD_USAGE;
   8797     }
   8798     if (is_sbus || is_sim) {
   8799         phy_devad = sal_strtoul(c, NULL, 0);
   8800         if (phy_devad > 0x1f) {
   8801             cli_out("ERROR: Invalid devad 0x%x, max=0x%x\n",
   8802                     phy_devad, 0x1f);
   8803             return CMD_FAIL;
   8804         }
   8805         /*
   8806          * If DEVAD is specified as X.Y then X is the DEVAD and Y
   8807          * is the lane number. For example DEVAD=1 and lane=2 is
   8808          * specified as 1.2 and encoded in phy_aer as 0x0802.
   8809          */
   8810         if ((c = sal_strchr(c, '.')) != NULL) {
   8811             c++;
   8812             phy_lane = sal_strtoul(c, NULL, 0);
   8813             /*next check lane number is greater than 7 for TSCBH */
   8814             if (phy_lane > 7) {
   8815                 cli_out("ERROR: Invalid phy_lane 0x%x, max=0x%x\n",
   8816                         phy_lane, 0x7);
   8817                 return CMD_FAIL;
   8818             } else {
   8819                 if (phy_lane > 3) {
   8820                     is_mpp1 = 1;
   8821                 }
   8822             }
   8823             if((c = sal_strchr(c, '.')) != NULL) {
   8824                 c++;
   8825                 phy_pindex = sal_strtoul(c, NULL, 0);
   8826             }
   8827         }
   8828 
   8829         /* need to check if TSCBH 8 lane, for pcs register lane 0-lane3 using MPP0
   8830         and lane 4-7 using MPP1, the bit location for MPP0 is 24 and MPP1 is 25 */
   8831         if (phy_devad == 0) {
   8832             if (is_mpp1) {
   8833                 phy_aer = 1 << 9;
   8834             } else {
   8835                 phy_aer = 1 << 8;
   8836             }
   8837             phy_aer |= (phy_devad << 11) | (phy_lane % 4);
   8838         } else {
   8839             phy_aer = (phy_devad << 11) | phy_lane | (phy_pindex << 8);
   8840         }
   8841         if ((c = ARG_GET(a)) == NULL) {     /* Get register number */
   8842             return CMD_USAGE;
   8843         }
   8844     } else  if (is_c45) {
   8845         phy_devad = sal_strtoul(c, NULL, 0);
   8846         if (phy_devad > 0x1f) {
   8847             cli_out("ERROR: Invalid devad 0x%x, max=0x%x\n",
   8848                     phy_devad, 0x1f);
   8849             return CMD_FAIL;
   8850         }
   8851         if ((c = ARG_GET(a)) == NULL) {     /* Get register number */
   8852             return CMD_USAGE;
   8853         }
   8854     }
   8855     phy_reg = sal_strtoul(c, NULL, 0);
   8856     if ((c = ARG_GET(a)) == NULL) { /* Read register */
   8857         if (is_sbus) {
   8858             phy_reg = (phy_aer << 16) | phy_reg;
   8859             rv = soc_sbus_mdio_read(u, phy_addr, phy_reg, &phy_data32);
   8860             phy_data = (uint16)phy_data32;
   8861         } else if (is_sim) {
   8862             phy_reg = (phy_aer << 16) | phy_reg;
   8863             rv = soc_physim_read(u, phy_addr, phy_reg, &phy_data);
   8864         } else if (is_c45) {
   8865             rv = soc_miimc45_read(u, phy_addr, phy_devad,
   8866                                   phy_reg, &phy_data);
   8867         } else {
   8868             rv = soc_miim_read(u, phy_addr, phy_reg, &phy_data);
   8869         }
   8870         if (rv < 0) {
   8871             cli_out("ERROR: MII Addr %d: soc_%s_read failed: %s\n",
   8872                     phy_addr, bus_name, soc_errmsg(rv));
   8873             return CMD_FAIL;
   8874         }
   8875         var_set_hex("phy_reg_data", phy_data, TRUE, FALSE);
   8876         cli_out("%s\t0x%02x: 0x%04x\n", "", phy_reg, phy_data);
   8877     } else {                /* write */
   8878         phy_data = sal_strtoul(c, NULL, 0);
   8879         if (is_sbus || is_sim) {
   8880             /*
   8881              * If register data is specified as X/Y then X is the
   8882              * data value and Y is the data mask. For example
   8883              * data=0x50 and mask=0xf0 is specified as 0x50/0xf0
   8884              * and encoded in phy_data32 as 0x0f000500.  Note that
   8885              * if the mask is not specified (or zero) then it is
   8886              * implicitly assumed to be 0xffff (all bits valid).
   8887              */
   8888             phy_data32 = phy_data;
   8889             phy_wrmask = 0;
   8890             if ((c = sal_strchr(c, '/')) != NULL) {
   8891                 c++;
   8892                 phy_wrmask = sal_strtoul(c, NULL, 0);
   8893                 phy_data32 |= (phy_wrmask << 16);
   8894             }
   8895             phy_reg = (phy_aer << 16) | phy_reg;
   8896             if (is_sbus) {
   8897                 rv = soc_sbus_mdio_write(u, phy_addr, phy_reg, phy_data32);
   8898             } else { /* is_sim */
   8899                 rv = soc_physim_wrmask(u, phy_addr,
   8900                                        phy_reg, phy_data, phy_wrmask);
   8901             }
   8902         } else if (is_c45) {
   8903             rv = soc_miimc45_write(u, phy_addr, phy_devad, phy_reg,
   8904                                    phy_data);
   8905         } else {
   8906             rv = soc_miim_write(u, phy_addr, phy_reg, phy_data);
   8907         }
   8908         if (rv < 0) {
   8909             cli_out("ERROR: MII Addr %d: soc_%s_write failed: %s\n",
   8910                     phy_addr, bus_name, soc_errmsg(rv));
   8911             return CMD_FAIL;
   8912         }
   8913     }
   8914     return CMD_OK;
   8915 }
   8916 
   8917 #if defined(BCM_ESW_SUPPORT) && defined(INCLUDE_PHY_8806X)
   8918 STATIC cmd_result_t
   8919 _phy_mt2(int unit, args_t *args)
   8920 {
   8921     mt2_sym_t *phy8806xsymbs = NULL;
   8922     parse_table_t pt;
   8923     bcm_pbmp_t pbm;
   8924     soc_port_t p, dport;
   8925     phy_ctrl_t *pc;
   8926     uint16 phy_addr;
   8927     char *port_str, *cmd_str, *regname, *regval, *fldname, *fldval;
   8928  #if defined(INCLUDE_FCMAP)   
   8929     char *fc_oper;
   8930     uint8 cmd = 0, show = 0;
   8931 #endif
   8932     char temp_char[2];
   8933     uint32 testno;
   8934     uint32 val1 = 0;
   8935     uint32 mt2_addr;
   8936     uint32 mt2_data[4];
   8937     uint32 mt2_field;
   8938     uint32 mt2_field_data[4];
   8939     uint32 flags = 0;
   8940     int i, j, tem, sbit, ebit, cnt, blkno = -1, min_idx = -1, max_idx = -1;
   8941     parse_pm_t ctr_options[] = {
   8942         {"All",         MT2_CTR_ALL},
   8943         {"SYs",         MT2_CTR_SYS},
   8944         {"LiNe",        MT2_CTR_LINE},
   8945         {"CHanged",     MT2_CTR_CHANGED},
   8946         {"Same",        MT2_CTR_SAME},
   8947         {"Zero",        MT2_CTR_ZERO},
   8948         {"NonZero",     MT2_CTR_NONZERO},
   8949         {"heX",         MT2_CTR_HEX},
   8950         {NULL,          0}
   8951     };
   8952 
   8953     BCM_PBMP_CLEAR(pbm);
   8954     port_str = NULL;
   8955 
   8956     if ((cmd_str = ARG_GET(args)) == NULL) {
   8957         cli_out ("Specify Operation.. getreg, setreg, getmem, setmem, gettotsc, settotsc, counter, dump or testrun\n");
   8958         return CMD_FAIL;
   8959     }
   8960 
   8961     if ((sal_strcasecmp(cmd_str, "counter") == 0) || (sal_strcasecmp(cmd_str, "ctr") == 0)) {
   8962         if ((cmd_str = ARG_GET(args)) == NULL) {
   8963             cli_out ("Specify subcommand.. start, stop, show , interval\n");
   8964             return CMD_FAIL;
   8965         }
   8966         if (sal_strcasecmp(cmd_str, "start") == 0) {
   8967             phy8806x_ctr_start(unit);
   8968             return CMD_OK;
   8969         } else if (sal_strcasecmp(cmd_str, "stop") == 0) {
   8970             phy8806x_ctr_stop(unit);
   8971             return CMD_OK;
   8972         } else if ((sal_strcasecmp(cmd_str, "show") == 0) || (sal_strcasecmp(cmd_str, "interval") == 0) ||
   8973                    (sal_strcasecmp(cmd_str, "fcevt") == 0)) {
   8974             if ((port_str = ARG_GET(args)) == NULL) {
   8975                 cli_out ("Specify port bitmap\n");
   8976                 return CMD_FAIL;
   8977             }
   8978             if (parse_bcm_pbmp(unit, port_str, &pbm) < 0) {
   8979                 cli_out("ERROR: unrecognized port bitmap: %s\n", port_str);
   8980                 return CMD_FAIL;
   8981             }
   8982         } else {
   8983             cli_out ("Invalid subcommand.. start, stop, show, interval\n");
   8984             return CMD_FAIL;
   8985         }
   8986         if (sal_strcasecmp(cmd_str, "interval") == 0) {
   8987             if ((regval = ARG_GET(args)) == NULL) {
   8988                 cli_out ("Specify the ctr task interval\n");
   8989                 return CMD_FAIL;
   8990             }
   8991             val1 = sal_ctoi(regval, 0);
   8992             /* coverity[overrun-local] */
   8993             DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   8994                 pc = EXT_PHY_SW_STATE(unit, p);
   8995                 if ((pc == NULL) || (phy_is_8806x(pc) != SOC_E_NONE)) {
   8996                     continue;
   8997                 }
   8998                 phy8806x_ctr_interval_set(pc, val1);
   8999             }
   9000  #if defined(INCLUDE_FCMAP) 
   9001         } else if (sal_strcasecmp(cmd_str, "fcevt") == 0) {
   9002             if ((regval = ARG_GET(args)) == NULL) {
   9003                 cli_out ("Specify FC event 0 - disable; 1 - enable\n");
   9004                 return CMD_FAIL;
   9005             }
   9006 
   9007             val1 = sal_ctoi(regval, 0);
   9008             if (val1 == 0) {
   9009                 cmd = 0xc;
   9010             } else if (val1 == 1) {
   9011                 cmd = 0xd;
   9012             }
   9013 
   9014             DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9015                 cli_out("FC Evt: u 0x%x, p 0x%x, cmd 0x%x\n", unit, p, cmd);
   9016                 bfcmap88060_xmod_debug_cmd(unit, p, cmd);
   9017             }
   9018 #endif
   9019         } else if (sal_strcasecmp(cmd_str, "show") == 0) {
   9020             while ((cmd_str = ARG_GET(args)) != NULL) {
   9021                 if (parse_mask(cmd_str, ctr_options, &flags)) {
   9022                     cli_out("Error: invalid option ignored: %s\n", cmd_str);
   9023                 }
   9024             }
   9025 
   9026             DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9027                 pc = EXT_PHY_SW_STATE(unit, p);
   9028                 if ((pc == NULL) || (phy_is_8806x(pc) != SOC_E_NONE)) {
   9029                     continue;
   9030                 }
   9031                 phy8806x_ctr_show(pc, flags);
   9032             }
   9033         }
   9034         return CMD_OK;
   9035     }
   9036 
   9037     if (!(sal_strcasecmp(cmd_str, "listreg") == 0)) {
   9038         if ((port_str = ARG_GET(args)) == NULL) {
   9039             cli_out("%s: ERROR: missing port bitmap\n", ARG_CMD(args));
   9040             return CMD_FAIL;
   9041         }
   9042         if (parse_bcm_pbmp(unit, port_str, &pbm) < 0) {
   9043            cli_out("ERROR: unrecognized port bitmap: %s\n", port_str);
   9044            return CMD_FAIL;
   9045         }
   9046     }
   9047 
   9048     if (sal_strcasecmp(cmd_str, "listreg") == 0) {
   9049         if ((regname = ARG_GET(args)) == NULL) {
   9050             cli_out ("Specify Partial register Name\n");
   9051             return CMD_FAIL;
   9052         }
   9053         i = 0;
   9054         while (i >= 0) {
   9055             i = mt2_syms_find_next_name(regname, &phy8806xsymbs, i);
   9056             if (i >= 0)
   9057             {
   9058                 cli_out("%s\n", phy8806xsymbs->name);
   9059             }
   9060         }
   9061         return CMD_OK;
   9062     } else if (sal_strcasecmp(cmd_str, "dump") == 0) {
   9063         if ((regname = ARG_GET(args)) == NULL) {
   9064             cli_out ("Specify AXI Address\n");
   9065             return CMD_FAIL;
   9066         }
   9067         mt2_addr = sal_ctoi(regname, 0);
   9068 
   9069         if ((regval = ARG_GET(args)) == NULL) {
   9070             val1 = 1;
   9071         } else {
   9072             val1 = sal_ctoi(regval, 0);
   9073         }
   9074 
   9075         DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9076             phy_addr = port_to_phyaddr(unit,p);
   9077             for (i = 0; i < val1; i++) {
   9078                 mt2_axi_read(unit, phy_addr, (mt2_addr + (i * 4)), mt2_data);
   9079                 /* To Do: Format Dump printout */
   9080                 cli_out("Reading at 0x%08x at phy addr 0x%02x = 0x%08x\n", (mt2_addr + (i * 4)), phy_addr, mt2_data[0]);
   9081             }
   9082         }
   9083     } else if ((sal_strcasecmp(cmd_str, "getreg") == 0) || (sal_strcasecmp(cmd_str, "setreg") == 0) || (sal_strcasecmp(cmd_str, "modreg") == 0)) {
   9084         parse_table_init(unit, &pt);
   9085         parse_table_add(&pt, "BLocK", PQ_DFL | PQ_INT, (void *)(-1), &blkno, 0);
   9086         if (parse_arg_eq(args, &pt) < 0) {
   9087             /* No Arguments. Don't have to do anything */
   9088         }
   9089         parse_arg_eq_done(&pt);
   9090 
   9091         if ((regname = ARG_GET(args)) == NULL) {
   9092             /* Display All Registers */
   9093             regname = &temp_char[0]; /* use a local char array to avoid memory leak */
   9094             sal_strcpy(regname, "r");
   9095         }
   9096         if (isint(regname)) {
   9097             cli_out("Reg operation by Address Not Implemented");
   9098             /* Display All Registers */
   9099             regname = &temp_char[0];
   9100             sal_strcpy(regname, "r");
   9101         }
   9102 
   9103         if ((phy8806xsymbs = mt2_syms_find_name(regname)) != NULL)
   9104         {
   9105             if (sal_strcasecmp(cmd_str, "setreg") == 0) {   /* Set Reg */
   9106                 if ((regval = ARG_GET(args)) == NULL) {
   9107                     cli_out ("Specify Value to Write\n");
   9108                     return CMD_FAIL;
   9109                 }
   9110                 if (sal_strcmp(regval, "POR") == 0) {
   9111                     mt2_data[0] = phy8806xsymbs->rstval;
   9112                     mt2_data[1] = phy8806xsymbs->rstval_hi;
   9113                 } else {
   9114                     if (phy8806xsymbs->flags & MT2_SYMBOL_FLAG_R64) {
   9115                         mt2_data[1] = sal_ctoi(regval, 0);
   9116                         if ((regval = ARG_GET(args)) == NULL) {
   9117                             cli_out ("Value Size Mismatch(64 bits) - Provide 2 words\n");
   9118                             return CMD_FAIL;
   9119                         }
   9120                     } else {
   9121                         mt2_data[1] = 0;
   9122                     }
   9123                     mt2_data[0] = sal_ctoi(regval, 0);
   9124                }
   9125 
   9126                 while (((fldname = ARG_GET(args)) != NULL) && ((fldval = ARG_GET(args)) != NULL)) {
   9127                     /* Search Fields */
   9128                     i = 0;
   9129                     while (1) {
   9130                         mt2_field = phy8806xsymbs->fields[i];
   9131                         j = (mt2_field >> 16) & 0x7fff;
   9132                         if (sal_strcasecmp(fldname, phy8806x_fields[j]) == 0) {
   9133                             sbit = (mt2_field & 0xff);
   9134                             ebit = ((mt2_field >> 8) & 0xff);
   9135                             if ((ebit - sbit) <= 31) {
   9136                                 j = sal_ctoi(fldval, 0);
   9137                                 mt2_field32_set(mt2_data, sbit, ebit, j);
   9138                                 cli_out ("Setting Field %s at %d - %d to %d\n", fldname, sbit, ebit, j);
   9139                             }
   9140                             break;
   9141                         }
   9142                         if (mt2_field & CDK_SYMBOL_FIELD_FLAG_LAST) {
   9143                             break;
   9144                         }
   9145                         i++;
   9146                     }
   9147                 }
   9148 
   9149                 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9150                      phy_addr = port_to_phyaddr(unit,p);
   9151                      mt2_sbus_reg_write(unit, phy_addr, blkno, phy8806xsymbs, mt2_data);
   9152                      if (phy8806xsymbs->flags & MT2_SYMBOL_FLAG_R64) {
   9153                          cli_out("Writing 0x%08x_%08x to reg %s at phy addr 0x%02x\n", mt2_data[1], mt2_data[0], regname, phy_addr);
   9154                      } else {
   9155                          cli_out("Writing 0x%08x to reg %s at phy addr 0x%02x\n", mt2_data[0], regname, phy_addr);
   9156                      }
   9157                 }
   9158             } else if (sal_strcasecmp(cmd_str, "modreg") == 0) {   /* Modify Reg */
   9159                 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9160                     phy_addr = port_to_phyaddr(unit,p);
   9161                     cli_out("Modify Register %s at phy addr 0x%02x\n", regname, phy_addr);
   9162                     mt2_sbus_reg_read(unit, phy_addr, blkno, phy8806xsymbs, mt2_data);
   9163                     tem = 0;
   9164                     while (((fldname = ARG_GET(args)) != NULL) && ((fldval = ARG_GET(args)) != NULL)) {
   9165                         /* Search Fields */
   9166                         i = 0;
   9167                         while (1) {
   9168                             mt2_field = phy8806xsymbs->fields[i];
   9169                             j = (mt2_field >> 16) & 0x7fff;
   9170                             if (sal_strcasecmp(fldname, phy8806x_fields[j]) == 0) {
   9171                                 sbit = (mt2_field & 0xff);
   9172                                 ebit = ((mt2_field >> 8) & 0xff);
   9173                                 if ((ebit - sbit) > 31) {
   9174                                     cli_out("Skipping 64-bit field %s\n", fldname);
   9175                                 } else {
   9176                                     j = sal_ctoi(fldval, 0);
   9177                                     mt2_field32_set(mt2_data, sbit, ebit, j);
   9178                                     tem = 1;
   9179                                     cli_out ("Setting Field %s at %d - %d to %d\n", fldname, sbit, ebit, j);
   9180                                 }
   9181                                 break;
   9182                             }
   9183                             
   9184                             if (mt2_field & CDK_SYMBOL_FIELD_FLAG_LAST) {
   9185                                 cli_out ("Not Found Field %s\n", fldname);
   9186                                 break;
   9187                             }
   9188                             i++;
   9189                         }
   9190                     }
   9191                     if (tem) { /* At least one field had changed.. */
   9192                         mt2_sbus_reg_write(unit, phy_addr, blkno, phy8806xsymbs, mt2_data);
   9193                     }
   9194                 }
   9195             } else {                                        /* Get Reg */
   9196                 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9197                     phy_addr = port_to_phyaddr(unit,p);
   9198                     mt2_sbus_reg_read(unit, phy_addr, blkno, phy8806xsymbs, mt2_data);
   9199                     if (phy8806xsymbs->flags & MT2_SYMBOL_FLAG_R64) {
   9200                         cli_out("%s.%s[0x%08x]= 0x%08x_%08x: <", phy8806xsymbs->name, port_str, phy8806xsymbs->addr, mt2_data[1], mt2_data[0]);
   9201                     } else {
   9202                         cli_out("%s.%s[0x%08x]= 0x%08x: <", phy8806xsymbs->name, port_str, phy8806xsymbs->addr, mt2_data[0]);
   9203                     }
   9204 
   9205                     /* Print Fields */
   9206                     i = 0;
   9207                     while (1) {
   9208                         if (!phy8806xsymbs->fields) {
   9209                             cli_out(" field info unavailable >\n");
   9210                             break;
   9211                         }
   9212                         mt2_field = phy8806xsymbs->fields[i];
   9213                         j = (mt2_field >> 16) & 0x7fff;
   9214                         sbit = (mt2_field & 0xff);
   9215                         ebit = ((mt2_field >> 8) & 0xff);
   9216                         mt2_field_get(mt2_data, sbit, ebit, mt2_field_data);
   9217                         if ((ebit - sbit) > 31) {
   9218                             cli_out("%s=0x%08x_%08x", phy8806x_fields[j], mt2_field_data[1], mt2_field_data[0]);
   9219                         } else {
   9220                             cli_out("%s=%d", phy8806x_fields[j], mt2_field_data[0]);
   9221                         }
   9222                         if (mt2_field & CDK_SYMBOL_FIELD_FLAG_LAST) {
   9223                             cli_out(">\n");
   9224                             break;
   9225                         } else {
   9226                             cli_out(", ");
   9227                         }
   9228                         i++;
   9229                     }
   9230                 }
   9231             }
   9232         } else {
   9233             cli_out("Reg Not Found. Possible registers are:\n");
   9234             i = 0;
   9235             while (i >= 0) {
   9236                 i = mt2_syms_find_next_name(regname, &phy8806xsymbs, i);
   9237                 if (i >= 0)
   9238                 {
   9239                     if (phy8806xsymbs->flags & MT2_SYMBOL_FLAG_REGISTER) {
   9240                         cli_out("%s\n", phy8806xsymbs->name);
   9241                     }
   9242                 }
   9243             }
   9244         }
   9245     } else if ((sal_strcasecmp(cmd_str, "getmem") == 0) || (sal_strcasecmp(cmd_str, "setmem") == 0)) {
   9246         parse_table_init(unit, &pt);
   9247         parse_table_add(&pt, "MINIdx", PQ_DFL | PQ_INT, (void *)(-1), &min_idx, 0);
   9248         parse_table_add(&pt, "MAXIdx", PQ_DFL | PQ_INT, (void *)(-1), &max_idx, 0);
   9249         parse_table_add(&pt, "BLocK", PQ_DFL | PQ_INT, (void *)(-1), &blkno, 0);
   9250 
   9251         if (parse_arg_eq(args, &pt) < 0) {
   9252             /* No Arguments. Don't have to do anything */
   9253         }
   9254         parse_arg_eq_done(&pt);
   9255 
   9256         if ((regname = ARG_GET(args)) == NULL) {
   9257             /* Display All Memories */
   9258             regname = &temp_char[0]; /* use local char array to avoid memory leak */
   9259             sal_strcpy(regname, "m");
   9260         }
   9261 
   9262         if (isint(regname)) {
   9263             cli_out("Mem operation by Address Not Implemented\n");
   9264             /* Display All Memories */
   9265             regname = &temp_char[0];
   9266             sal_strcpy(regname, "m");
   9267         }
   9268 
   9269         if ((phy8806xsymbs = mt2_syms_find_name(regname)) != NULL)
   9270         {
   9271             cnt = (phy8806xsymbs->index & 0xff) / 4;    /* Number of 32-bit words */
   9272             if (min_idx == -1) {
   9273                 min_idx = MT2_SYMBOL_INDEX_MIN_DECODE(phy8806xsymbs->index);
   9274             }
   9275             if (max_idx == -1) {
   9276                 max_idx = MT2_SYMBOL_INDEX_MAX_DECODE(phy8806xsymbs->index);
   9277             }
   9278 
   9279             if (sal_strcasecmp(cmd_str, "setmem") == 0) {   /* Set Mem */
   9280                 for (i = 1; i <= cnt; i++) {
   9281                     if ((regval = ARG_GET(args)) == NULL) {
   9282                         cli_out ("Value Size Mismatch(%d bits) - Provide %d words\n", (cnt*32), cnt);
   9283                         return CMD_FAIL;
   9284                     }
   9285                     mt2_data[cnt-i] = sal_ctoi(regval, 0);
   9286                 }
   9287                 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9288                     phy_addr = port_to_phyaddr(unit,p);
   9289                     for (i = min_idx; i <= max_idx; i++) {
   9290                         mt2_sbus_mem_write(unit, phy_addr, blkno, phy8806xsymbs, i, mt2_data);
   9291                         cli_out("Writing %d words to mem %s[%d] at phy addr 0x%02x\n", cnt, regname, i, phy_addr);
   9292                     }
   9293                 }
   9294             } else {                                        /* Get Mem */
   9295                 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9296                     phy_addr = port_to_phyaddr(unit,p);
   9297                     for (i = min_idx; i <= max_idx; i++) {
   9298                         mt2_sbus_mem_read(unit, phy_addr, blkno, phy8806xsymbs, i, mt2_data);
   9299                         cli_out("Reading mem %s[%d] at phy addr 0x%02x = 0x", regname, i, phy_addr);
   9300                         for (j = 1; j <= cnt; j++) {
   9301                             cli_out("%08x%s", mt2_data[cnt-j], (j == cnt) ? "\n" : "_");
   9302                         }
   9303                     }
   9304                 }
   9305             }
   9306         } else {
   9307             cli_out("memory Not Found. Possible memories are:\n");
   9308             i = 0;
   9309             while (i >= 0) {
   9310                 i = mt2_syms_find_next_name(regname, &phy8806xsymbs, i);
   9311                 if (i >= 0)
   9312                 {
   9313                     if (phy8806xsymbs->flags & MT2_SYMBOL_FLAG_MEMORY) {
   9314                         cli_out("%s\n", phy8806xsymbs->name);
   9315                     }
   9316                 }
   9317             }
   9318         }
   9319         return CMD_OK;
   9320     } else if ((sal_strcasecmp(cmd_str, "gettotsc") == 0) || (sal_strcasecmp(cmd_str, "settotsc") == 0)) {
   9321         if ((regname = ARG_GET(args)) == NULL) {
   9322             cli_out("Specify Address\n");
   9323             return CMD_FAIL;
   9324         }
   9325         if (!isint(regname)) {
   9326             cli_out("To-TSC Symbolic Name Not Implemented. Give Address\n");
   9327             return CMD_FAIL;
   9328         }
   9329         mt2_addr = sal_ctoi(regname, 0);
   9330         if (sal_strcasecmp(cmd_str, "settotsc") == 0) {   /* Set To-Tsc Reg */
   9331             if ((regval = ARG_GET(args)) == NULL) {
   9332                 cli_out ("Specify Value to Write\n");
   9333                 return CMD_FAIL;
   9334             }
   9335             tem = 0;
   9336             parse_table_init(unit, &pt);
   9337             parse_table_add(&pt, "Mask", PQ_DFL | PQ_INT, 0, &tem, 0);
   9338             if (parse_arg_eq(args, &pt) < 0) {
   9339                 /* No Arguments. Mask is 0 */
   9340             }
   9341             parse_arg_eq_done(&pt);
   9342             mt2_data[0] = sal_ctoi(regval, 0) << 16;
   9343             mt2_data[0] |= (tem & 0xffff);
   9344 
   9345             DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9346                  phy_addr = port_to_phyaddr(unit,p);
   9347                  mt2_sbus_to_tsc_write(unit, phy_addr, mt2_addr, mt2_data);
   9348                  cli_out("Writing 0x%08x to to_tsc reg 0x%08x at phy addr 0x%02x\n", mt2_data[0], mt2_addr, phy_addr);
   9349             }
   9350         } else {                                           /* Set To-Tsc Reg */
   9351             DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9352                  phy_addr = port_to_phyaddr(unit,p);
   9353                  mt2_sbus_to_tsc_read(unit, phy_addr, mt2_addr, mt2_data);
   9354                  cli_out("Reading to_tsc reg 0x%08x at phy addr 0x%02x = 0x%08x\n", mt2_addr, phy_addr, mt2_data[0]);
   9355             }
   9356         }
   9357 
   9358         return CMD_OK;
   9359     } else if ((sal_strcasecmp(cmd_str, "testrun") == 0) || (sal_strcasecmp(cmd_str, "tr") == 0)) {
   9360         if ((regname = ARG_GET(args)) == NULL) {
   9361             cli_out ("Specify Test Number\n");
   9362             return CMD_FAIL;
   9363         }
   9364         i = 0;
   9365         if (sal_strcasecmp(regname, "-s") == 0) {
   9366             i = 1;   /* Silent / Summary Only */
   9367             if ((regname = ARG_GET(args)) == NULL) {
   9368                 cli_out ("Specify Test Number\n");
   9369                 return CMD_FAIL;
   9370             }
   9371         }
   9372         testno = sal_ctoi(regname, 0);
   9373 
   9374         /* PORT_LOCK(unit); */
   9375         DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9376              phy_addr = port_to_phyaddr(unit,p);
   9377              mt2_test_run(unit, phy_addr, testno, i);
   9378         }
   9379     } else if (sal_strcasecmp(cmd_str, "ether") == 0) {
   9380         DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9381             if (phy8806x_xmod_debug_cmd(unit, p) == SOC_E_UNAVAIL)
   9382                 bsl_printf("Command not supported in FC mode \n");
   9383         }
   9384         /* PORT_UNLOCK(unit); */
   9385 #if defined(INCLUDE_FCMAP)
   9386     } else if (sal_strcasecmp(cmd_str, "fc") == 0) {
   9387         if ((fc_oper = ARG_GET(args)) == NULL) {
   9388             cli_out ("Specify FC operation..\n");
   9389             return CMD_FAIL;
   9390         }
   9391 
   9392         if (sal_strcasecmp(fc_oper, "dmpstat") == 0) {
   9393             cmd = 0x5;
   9394         }
   9395 
   9396         if (sal_strcasecmp(fc_oper, "clrstat") == 0) {
   9397             cmd = 0x6;
   9398         }
   9399 
   9400         if (sal_strcasecmp(fc_oper, "dmpdbg") == 0) {
   9401             cmd = 0x7;
   9402         }
   9403 
   9404         if (sal_strcasecmp(fc_oper, "disable") == 0) {
   9405             cmd = 0x8;
   9406         }
   9407 
   9408         if (sal_strcasecmp(fc_oper, "syslnk") == 0) {
   9409             cmd = 0x9;
   9410         }
   9411         if (sal_strcasecmp(fc_oper, "admn") == 0) {
   9412             cmd = 0xa;
   9413         }
   9414         if (sal_strcasecmp(fc_oper, "clkvld") == 0) {
   9415             cmd = 0xb;
   9416         }
   9417         if (sal_strcasecmp(fc_oper, "speed") == 0) {
   9418             cmd = 0x4;
   9419         }
   9420 
   9421         if (sal_strcasecmp(fc_oper, "showcfg") == 0) {
   9422             show = 0x1;
   9423         }
   9424 
   9425         DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9426             if (show == 0x1) {
   9427                 cli_out("FC CFG for port %d\n", p);
   9428                 bfcmap88060_show_fc_config(unit, p);
   9429             } else {
   9430                 cli_out("FC OPER: u 0x%x, p 0x%x, oper %s cmd 0x%x\n", unit, p, fc_oper, cmd);
   9431                 bfcmap88060_xmod_debug_cmd(unit, p, cmd);
   9432             }
   9433         }
   9434 #endif
   9435     } else if (sal_strcasecmp(cmd_str, "diag") == 0) {
   9436         if ((cmd_str = ARG_GET(args)) == NULL) {
   9437             cli_out ("Specify Diag Command\n");
   9438             return CMD_FAIL;
   9439         }
   9440         regname = ARG_GET(args); /* recycle regname for Optional Parameter */
   9441         DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9442             pc = EXT_PHY_SW_STATE(unit, p);
   9443             if ((pc == NULL) || (phy_is_8806x(pc) != SOC_E_NONE)) {
   9444                 continue;
   9445             }
   9446             phy_addr = port_to_phyaddr(unit,p);
   9447             mt2_diag_run(unit, phy_addr, cmd_str, regname);
   9448         }
   9449     } else if (sal_strcasecmp(cmd_str, "uart") == 0) {
   9450         void *buffer, *buf;
   9451         char *fn = NULL, file_name[81];
   9452         unsigned char *cbuf;
   9453         parse_table_t pt;
   9454         int lscan_time;
   9455         unsigned int buf_size = 4096; /* NULL termination taken care of internally */
   9456 
   9457         parse_table_init(unit, &pt);
   9458         parse_table_add(&pt, "File", PQ_STRING, 0, &fn, NULL);
   9459         parse_table_add(&pt, "BufSize", PQ_DFL | PQ_INT, 0, &buf_size, 0);
   9460 
   9461         if (parse_arg_eq(args, &pt) < 0) {
   9462             cli_out("Dumping to the screen: %s\n", ARG_CUR(args));
   9463             file_name[0] = 0;
   9464         } else {
   9465             sal_strncpy(file_name, fn, 80);
   9466         }
   9467         parse_arg_eq_done(&pt);
   9468 
   9469         buffer = (void*) sal_alloc(buf_size, "mt2 uart buffer");
   9470 
   9471         if (buffer == NULL) {
   9472             cli_out("Insufficient memory.\n");
   9473             return CMD_FAIL;
   9474         }
   9475         /* rounding up to the next 4 byte boundary */
   9476         buf = UINTPTR_TO_PTR(((PTR_TO_UINTPTR(buffer) + 0x3) & ~0x3));
   9477 
   9478         cbuf = (unsigned char *) buf;
   9479         buf_size -= (PTR_TO_UINTPTR(buffer) & 0x3) + 4;
   9480         cbuf[0] = buf_size & 0xff;
   9481         cbuf[1] = (buf_size >> 8) & 0xff;
   9482         cbuf[2] = (buf_size >> 16) & 0xff;
   9483         cbuf[3] = (buf_size >> 24) & 0xff;
   9484         buf = UINTPTR_TO_PTR(PTR_TO_UINTPTR(buf) + 0x4);
   9485 
   9486         BCM_IF_ERROR_RETURN(bcm_linkscan_enable_get(unit, &lscan_time));
   9487         if (lscan_time != 0) {
   9488             cli_out("Stopping Linkscan.\n");
   9489             BCM_IF_ERROR_RETURN(bcm_linkscan_enable_set(unit, 0));
   9490             /* Give enough time for linkscan task to exit. */
   9491             sal_usleep(lscan_time * 2);
   9492         }
   9493 
   9494         {
   9495 #ifndef  NO_FILEIO
   9496             FILE *ofp = NULL;
   9497             if ((ofp = sal_fopen(file_name, "w")) != NULL) {
   9498                 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9499                         sal_fprintf(ofp, "-------------- Start Port %s --------------\n", SOC_PORT_NAME(unit, p));
   9500                         do {
   9501                             if (port_diag_ctrl(unit, p, 0,
   9502                                    PHY_DIAG_CTRL_GET, PHY_DIAG_CTRL_STATE_GENERIC, buf) == BCM_E_NONE) {
   9503                                 sal_fprintf(ofp, "%s", (char*) buf);
   9504                             } else {
   9505                                 sal_fprintf(ofp, "PHY_DIAG_CTRL_GET (PHY_DIAG_CTRL_STATE_GENERIC) failed for %s !.\n", SOC_PORT_NAME(unit, p));
   9506                                 cli_out("PHY_DIAG_CTRL_GET (PHY_DIAG_CTRL_STATE_GENERIC) failed for %s !.\n", SOC_PORT_NAME(unit, p));
   9507                                 break;
   9508                             }
   9509                             /* cli_out("available_size =%d sal_strlen = %d\n", buf_size, sal_strlen((char*) buf)); */
   9510                         } while (sal_strlen((char*) buf) >= (buf_size - 8)); /* full buffer returned */
   9511                         sal_fprintf(ofp, "\n-------------- End Port %s ----------------\n", SOC_PORT_NAME(unit, p));
   9512                 }
   9513                 sal_fclose(ofp);
   9514             } else
   9515 #endif
   9516             {
   9517                 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) {
   9518                         cli_out("-------------- Start Port %s --------------\n", SOC_PORT_NAME(unit, p));
   9519                         do {
   9520                             if (port_diag_ctrl(unit, p, 0,
   9521                                    PHY_DIAG_CTRL_GET, PHY_DIAG_CTRL_STATE_GENERIC, buf) == BCM_E_NONE) {
   9522                                 cli_out("%s", (char*) buf);
   9523                             } else {
   9524                                 cli_out("PHY_DIAG_CTRL_GET (PHY_DIAG_CTRL_STATE_GENERIC) failed for %s !.\n", SOC_PORT_NAME(unit, p));
   9525                                 break;
   9526                             }
   9527                             /* cli_out("available_size =%d sal_strlen = %d\n", buf_size, sal_strlen((char*) buf)); */
   9528                         } while (sal_strlen((char*) buf) >= (buf_size - 8)); /* full buffer returned */
   9529                         cli_out("\n-------------- End Port %s ----------------\n", SOC_PORT_NAME(unit, p));
   9530                 }
   9531             }
   9532         }
   9533         if (lscan_time != 0) {
   9534             cli_out("Restarting Linkscan.\n");
   9535             BCM_IF_ERROR_RETURN(bcm_linkscan_enable_set(unit, lscan_time));
   9536         }
   9537         sal_free(buffer);
   9538     } else {
   9539         cli_out ("Unknown Operation : %s\n", cmd_str);
   9540         return CMD_FAIL;
   9541     }
   9542 
   9543     return CMD_OK;
   9544 }
   9545 #endif /* defined(BCM_ESW_SUPPORT) && defined(INCLUDE_PHY_8806X) */
   9546 
   9547 /*
   9548  * Function:    if_phy
   9549  * Purpose:     Show/configure phy registers.
   9550  * Parameters:  u - SOC unit #
   9551  *              a - pointer to args
   9552  * Returns:     CMD_OK/CMD_FAIL/
   9553  */
   9554 cmd_result_t if_esw_phy(int u, args_t *a)
   9555 {
   9556     soc_pbmp_t pbm, pbm_phys, pbm_temp;
   9557     soc_port_t p, dport;
   9558     char *c, drv_name[64];
   9559     uint16 phy_data, phy_devad = 0;
   9560     uint16 phy_addr;
   9561     uint32 phy_reg;
   9562     uint32 phy_data32;
   9563     int int_ovrride; /* Set if no external PHY is present */
   9564     int intermediate = 0;
   9565     int is_c45 = 0;
   9566 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT)
   9567     int is_rcpu = 0;
   9568 #endif                          /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */
   9569     int rv = 0;
   9570     char pfmt[SOC_PBMP_FMT_LEN];
   9571     int i;
   9572     int p_devad[] = { PHY_C45_DEV_PMA_PMD,
   9573         PHY_C45_DEV_WIS,
   9574         PHY_C45_DEV_PCS,
   9575         PHY_C45_DEV_PHYXS,
   9576         PHY_C45_DEV_DTEXS,
   9577         PHY_C45_DEV_AN,
   9578         PHY_C45_DEV_USER
   9579     };
   9580     char *p_devad_str[] = { "DEV_PMA_PMD",
   9581         "DEV_WIS",
   9582         "DEV_PCS",
   9583         "DEV_PHYXS",
   9584         "DEV_DTEXS",
   9585         "DEV_AN",
   9586         "DEV_USER"
   9587     };
   9588 #ifdef PORTMOD_SUPPORT
   9589     int nof_phys =0;
   9590 #endif
   9591 
   9592     if (!sh_check_attached(ARG_CMD(a), u)) {
   9593         return CMD_FAIL;
   9594     }
   9595 
   9596     c = ARG_GET(a);
   9597 
   9598     if (c != NULL && sal_strcasecmp(c, "info") == 0) {
   9599         return _if_esw_phy_info(u, a);
   9600     }
   9601 
   9602 #if defined(PHYMOD_SUPPORT)
   9603     if (c != NULL && sal_strcasecmp(c, "phymod") == 0) {
   9604         return _if_esw_phy_phymod(u, a);
   9605     }
   9606 #endif /* defined(PHYMOD_SUPPORT) */
   9607 
   9608     if (c != NULL && sal_strcasecmp(c, "eee") == 0) {
   9609         return _if_esw_phy_eee(u, a);
   9610     }
   9611 
   9612 #ifdef   INCLUDE_TIMESYNC_DVT_TESTS    /* test IEEE1588 TimeSync */
   9613     if (c != NULL && sal_strncasecmp(c, "tst", 3) == 0) {
   9614         return phy_test1588(u, a, &pbm);
   9615     }
   9616 #endif
   9617 
   9618     if ( c != NULL && 
   9619          ((sal_strcasecmp(c, "TS")       == 0) ||
   9620           (sal_strcasecmp(c, "TimeSync") == 0)) ) {
   9621         return _if_esw_phy_timesync(u, a);
   9622     }
   9623 
   9624 #ifdef INCLUDE_PHY_SYM_DBG
   9625     if (c != NULL && sal_strcasecmp(c, "SymDebug") == 0) {
   9626         return _if_esw_phy_symdebug(u, a);
   9627     }
   9628 
   9629     if (c != NULL && sal_strcasecmp(c, "SymDebugOff") == 0) {
   9630         return _if_esw_phy_symdebug_off(u, a);
   9631     }
   9632 #endif
   9633 
   9634     if (c != NULL && sal_strcasecmp(c, "firmware") == 0) {
   9635         return _if_esw_phy_firmware(u, a);
   9636     }
   9637 
   9638     if (c != NULL && sal_strcasecmp(c, "oam") == 0) {
   9639         return _if_esw_phy_oam(u, a);
   9640     }
   9641 
   9642     if (c != NULL && sal_strcasecmp(c, "power") == 0) {
   9643         return _if_esw_phy_power(u, a);
   9644     }
   9645 
   9646     if (c != NULL && sal_strcasecmp(c, "margin") == 0) {
   9647         return _if_esw_phy_margin(u, a);
   9648     }
   9649 
   9650     if (c != NULL && sal_strcasecmp(c, "prbs") == 0) {
   9651         return _if_esw_phy_prbs(u, a);
   9652     }
   9653 
   9654     if (c != NULL && sal_strcasecmp(c, "diag") == 0) {
   9655         return _if_esw_phy_diag(u, a);
   9656     }
   9657 
   9658     if (c != NULL && sal_strcasecmp(c, "longreach") == 0) {
   9659         return _if_esw_phy_longreach(u, a);
   9660     }
   9661 
   9662     if (c != NULL && sal_strcasecmp(c, "extlb") == 0) {
   9663         return _if_esw_phy_extlb(u, a);
   9664     }
   9665 
   9666     if (c != NULL && sal_strcasecmp(c, "clock") == 0) {
   9667         return _if_esw_phy_clock(u, a);
   9668     }
   9669 
   9670     if (c != NULL && sal_strcasecmp(c, "wr") == 0) {
   9671         return _if_esw_phy_wr(u, a);
   9672     }
   9673 
   9674     if (c != NULL && sal_strcasecmp(c, "rd_cp") == 0) {
   9675         return _if_esw_phy_rd_cp(u, a);
   9676     }
   9677 
   9678     if (c != NULL && sal_strcasecmp(c, "rd_cp2") == 0) {
   9679         return _if_esw_phy_rd_cp2(u, a);
   9680     }
   9681 
   9682     if (c != NULL && sal_strcasecmp(c, "mod") == 0) {
   9683         return _if_esw_phy_mod(u, a);
   9684     }
   9685 
   9686     if (c != NULL && sal_strcasecmp(c, "control") == 0) {
   9687         return _if_esw_phy_control(u, a);
   9688     }
   9689 
   9690     /* All access to an MII register */
   9691     if (c != NULL && sal_strcasecmp(c, "dumpall") == 0) {
   9692         return _if_esw_phy_dumpall(u, a);
   9693     }
   9694 
   9695     /* Raw access to an MII register */
   9696     if (c != NULL && sal_strcasecmp(c, "raw") == 0) {
   9697         return _if_esw_phy_raw(u, a);
   9698     }
   9699 
   9700 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT)
   9701     if (c != NULL && sal_strcasecmp(c, "rcpu") == 0) {
   9702         is_rcpu = 1;
   9703         c = ARG_GET(a);
   9704     }
   9705 #endif                          /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */
   9706 
   9707     if (c != NULL && sal_strcasecmp(c, "int") == 0) {
   9708         intermediate = 1;
   9709         c = ARG_GET(a);
   9710     }
   9711 
   9712 #if defined(BCM_ESW_SUPPORT) && defined(INCLUDE_PHY_8806X)
   9713     if (c != NULL && sal_strcasecmp(c, "mt2") == 0) {
   9714         return _phy_mt2(u, a);
   9715     }
   9716 #endif /* defined(BCM_ESW_SUPPORT) && defined(INCLUDE_PHY_8806X) */
   9717 
   9718 
   9719     if (c == NULL) {
   9720         return (CMD_USAGE);
   9721     }
   9722 
   9723     /* Parse the bitmap. */
   9724     if (parse_pbmp(u, c, &pbm) < 0) {
   9725         cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c);
   9726         return CMD_FAIL;
   9727     }
   9728 
   9729     SOC_PBMP_ASSIGN(pbm_phys, pbm);
   9730     SOC_PBMP_AND(pbm_phys, PBMP_PORT_ALL(u));
   9731     if (SOC_PBMP_IS_NULL(pbm_phys)) {
   9732         cli_out("Ports specified do not have PHY drivers.\n");
   9733     } else {
   9734         SOC_PBMP_ASSIGN(pbm_temp, pbm);
   9735         SOC_PBMP_REMOVE(pbm_temp, PBMP_PORT_ALL(u));
   9736         if (SOC_PBMP_NOT_NULL(pbm_temp)) {
   9737             cli_out("Not all ports given have PHY drivers.  Using %s\n",
   9738                     SOC_PBMP_FMT(pbm_phys, pfmt));
   9739         }
   9740     }
   9741     SOC_PBMP_ASSIGN(pbm, pbm_phys);
   9742 
   9743     if (ARG_CNT(a) == 0) {      /*  show information for all registers */
   9744 #if defined(BCM_TOMAHAWK3_SUPPORT)
   9745         if (SOC_IS_TOMAHAWK3(u)) {
   9746             cli_out("Tomahawk 3 does not support MDIO. Please use phy <pbm> *\n\n\n");
   9747             return (CMD_USAGE);
   9748         }
   9749 
   9750 #endif
   9751         DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   9752             phy_addr = (intermediate ?
   9753                         port_to_phyaddr_int(u, p) : port_to_phyaddr(u, p));
   9754             int_ovrride = (EXT_PHY_SW_STATE(u, p) == NULL) ? 1 : 0;
   9755             if (phy_addr == 0xff) {
   9756                 cli_out("Port %s: No %sPHY address assigned\n",
   9757                         SOC_PORT_NAME(u, p),
   9758                         intermediate ? "intermediate " : "");
   9759                 continue;
   9760             }
   9761 #ifdef PORTMOD_SUPPORT
   9762             if (soc_feature(u, soc_feature_portmod)) {
   9763                 portmod_port_num_phys_get(u, p, &nof_phys);
   9764                 int_ovrride = 0;
   9765                 if (nof_phys == 1) {
   9766                     is_c45 = 0;
   9767                 } else {
   9768                     is_c45 = portmod_port_flags_test(u, p, PHY_FLAGS_C45);
   9769                 }
   9770             } else
   9771 #endif
   9772             {
   9773                 is_c45 = soc_phy_is_c45_miim(u, p);
   9774             }
   9775 
   9776             if (intermediate) {
   9777                 cli_out("Port %s (intermediate PHY addr 0x%02x):",
   9778                         SOC_PORT_NAME(u, p), phy_addr);
   9779             } else {
   9780                 int ap = p;
   9781                 char lnstr[32];
   9782 
   9783 #ifdef PORTMOD_SUPPORT
   9784                 if(soc_feature(u, soc_feature_portmod)) {
   9785                     phymod_core_access_t core_acc;
   9786                     phymod_core_info_t   core_info;
   9787                     int nof_cores = 0;
   9788                     int phy = 0, core_num = 0, is_legacy =0;
   9789                     int range_start = 0;
   9790                     int is_first_range;
   9791                     portmod_port_diag_info_t diag_info;
   9792                     int diag_rv;
   9793                     uint8 pcount=0;
   9794                     char *pname, namelen; 
   9795 
   9796                     phymod_core_access_t_init(&core_acc);
   9797                     phymod_core_info_t_init(&core_info);
   9798                     sal_memset(&diag_info, 0, sizeof(portmod_port_diag_info_t));
   9799 
   9800                     portmod_port_main_core_access_get(u, p, -1, &core_acc, &nof_cores);
   9801                     if(nof_cores == 0) {
   9802                         continue;
   9803                     }
   9804                     /* check if the phy is a legacy phy */
   9805                     diag_rv = portmod_port_check_legacy_phy(u, p, &is_legacy);
   9806                     if (diag_rv) {
   9807                         continue;
   9808                     }
   9809                     if ( !is_legacy ) {
   9810                         diag_rv = portmod_port_diag_info_get(u, p, &diag_info);
   9811                         if(diag_rv){
   9812                             continue;
   9813                         }
   9814 
   9815                         diag_rv = portmod_port_core_num_get(u, p, &core_num);
   9816                         if (diag_rv){
   9817                             continue;
   9818                         }
   9819 
   9820                         is_first_range = TRUE;
   9821                         BCM_PBMP_ITER(diag_info.phys, phy){
   9822                             if( is_first_range ){
   9823                                 range_start = phy ;
   9824                                 is_first_range = FALSE;
   9825                             }
   9826                         }
   9827 
   9828                         SOC_IF_ERROR_RETURN
   9829                             (phymod_core_info_get(&core_acc, &core_info));
   9830 
   9831                         SOC_PBMP_COUNT(diag_info.phys, pcount);
   9832 
   9833                         pname = phymod_core_version_t_mapping[core_info.core_version].key;
   9834                         namelen = strlen(pname);
   9835 
   9836                         sal_snprintf(lnstr, sizeof(lnstr), "%s", pname);
   9837                         sal_snprintf(lnstr+namelen-2, sizeof(lnstr)-(namelen-2), "-%s/%02d/", pname+namelen-2, core_num); 
   9838 
   9839                         pname = lnstr;
   9840                         while (*pname != '-') {
   9841                             *pname = sal_toupper(*pname);
   9842                             pname++;
   9843                         }
   9844 
   9845                         pname = lnstr+strlen(lnstr);
   9846                         if (pcount == 4)
   9847                             sal_snprintf(pname,sizeof(lnstr), "%d", pcount);
   9848                         else if (pcount == 2)
   9849                             sal_snprintf(pname,sizeof(lnstr), "%d-%d", (range_start-1)%4, ((range_start-1)%4)+1);
   9850                         else
   9851                             sal_snprintf(pname,sizeof(lnstr), "%d", (range_start-1)%4);
   9852                     }else {
   9853                         sal_snprintf(lnstr, sizeof(lnstr), "%s", soc_phy_name_get(u, p));
   9854                     }
   9855                 }else
   9856 #endif
   9857                 {
   9858                     sal_snprintf(lnstr, sizeof(lnstr), "%s", soc_phy_name_get(u, p));
   9859                 }
   9860 
   9861                 BCM_API_XLATE_PORT_P2A(u, &ap); /* Use BCM API port */
   9862                 BCM_IF_ERROR_RETURN(bcm_port_phy_drv_name_get
   9863                                     (u, ap, drv_name, 64));
   9864                 cli_out("Port %s (PHY addr 0x%02x): %s (%s)",
   9865                         (SOC_PORT_VALID_RANGE(u, p) ? SOC_PORT_NAME(u, p):"unknown"),
   9866                         phy_addr, lnstr,
   9867                         drv_name);
   9868             }
   9869             if (is_c45 && !intermediate && !int_ovrride) {
   9870                 for (i = 0; i < COUNTOF(p_devad); i++) {
   9871                     phy_devad = p_devad[i];
   9872                     cli_out("\nDevAd = %d(%s)", phy_devad, p_devad_str[i]);
   9873                     for (phy_reg = PHY_MIN_REG; phy_reg <= PHY_MAX_REG;
   9874                          phy_reg++) {
   9875 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT)
   9876                         if (1 == is_rcpu) {
   9877                             rv = soc_rcpu_miimc45_read(u, phy_addr,
   9878                                                        phy_devad, phy_reg,
   9879                                                        &phy_data);
   9880                         } else
   9881 #endif                          /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */
   9882                         if (EXT_PHY_SW_STATE(u, p) &&
   9883                                 (EXT_PHY_SW_STATE(u, p)->read)) {
   9884                             rv = EXT_PHY_SW_STATE(u, p)->read(u, phy_addr,
   9885                                                               BCM_PORT_PHY_CLAUSE45_ADDR
   9886                                                               (phy_devad,
   9887                                                                phy_reg),
   9888                                                               &phy_data);
   9889                         } else if(soc_feature(u, soc_feature_portmod)) {
   9890                             rv = soc_miimc45_read(u, phy_addr,
   9891                                                   phy_devad, phy_reg,
   9892                                                   &phy_data);
   9893                         } else {
   9894                             rv = soc_miimc45_read(u, phy_addr,
   9895                                                   phy_devad, phy_reg,
   9896                                                   &phy_data);
   9897                         }
   9898 
   9899                         if (rv < 0) {
   9900                             cli_out("\nERROR: Port %s: "
   9901                                     "soc_miim_read failed: %s\n",
   9902                                     SOC_PORT_NAME(u, p), soc_errmsg(rv));
   9903 			    return CMD_FAIL;
   9904                         }
   9905                         cli_out("%s\t0x%04x: 0x%04x",
   9906                                 ((phy_reg % DUMP_PHY_COLS) == 0) ? "\n" : "",
   9907                                 phy_reg, phy_data);
   9908                     }
   9909                 }
   9910             } else {
   9911                 for (phy_reg = PHY_MIN_REG; phy_reg <= PHY_MAX_REG; phy_reg++) {
   9912 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT)
   9913                     if (1 == is_rcpu) {
   9914                         rv = soc_rcpu_miim_read(u, phy_addr, phy_reg,
   9915                                                 &phy_data);
   9916                     } else
   9917 #endif                          /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */
   9918                     if (!intermediate && !int_ovrride) {
   9919                         if (EXT_PHY_SW_STATE(u, p) &&
   9920                             (EXT_PHY_SW_STATE(u, p)->read)) {
   9921                             rv = EXT_PHY_SW_STATE(u, p)->read(u, phy_addr,
   9922                                                               phy_reg,
   9923                                                               &phy_data);
   9924                         } else if(soc_feature(u, soc_feature_portmod)) {
   9925                             rv = soc_sbus_mdio_read(u, phy_addr, phy_reg, &phy_data32);
   9926                             phy_data = (uint16)phy_data32;
   9927                         } else {
   9928                             rv = soc_miim_read(u, phy_addr, phy_reg, &phy_data);
   9929                         }
   9930                     } else {
   9931                         if (INT_PHY_SW_STATE(u, p) &&
   9932                             (INT_PHY_SW_STATE(u, p)->read)) {
   9933                             rv = INT_PHY_SW_STATE(u, p)->read(u, phy_addr,
   9934                                                               phy_reg,
   9935                                                               &phy_data);
   9936                         } else if(soc_feature(u, soc_feature_portmod)) {
   9937                             rv = soc_sbus_mdio_read(u, phy_addr, phy_reg, &phy_data32);
   9938                             phy_data = (uint16)phy_data32;
   9939                         } else {
   9940                             rv = soc_miim_read(u, phy_addr, phy_reg, &phy_data);
   9941                         }
   9942                     }
   9943                     if (rv < 0) {
   9944                         cli_out("\nERROR: Port %s: soc_miim_read failed: %s\n",
   9945                                 SOC_PORT_NAME(u, p), soc_errmsg(rv));
   9946 			return CMD_FAIL;
   9947                     }
   9948                     cli_out("%s\t0x%02x: 0x%04x",
   9949                             ((phy_reg % DUMP_PHY_COLS) == 0) ? "\n" : "",
   9950                             phy_reg, phy_data);
   9951                 }
   9952             }
   9953             cli_out("\n");
   9954         }
   9955     } else {                    /* get register argument */
   9956 
   9957 #if defined(PHYMOD_SUPPORT)
   9958         if (!isint(ARG_CUR(a))) {
   9959             return phymod_sym_access(u, a, intermediate, &pbm);
   9960         }
   9961 #endif /* defined(PHYMOD_SUPPORT) */
   9962 
   9963         c = ARG_GET(a);
   9964         phy_reg = sal_ctoi(c, 0);
   9965 
   9966         if (ARG_CNT(a) == 0) {  /* no more args; show this register */
   9967             DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
   9968                 phy_addr = (intermediate ?
   9969                             port_to_phyaddr_int(u, p) : port_to_phyaddr(u, p));
   9970                 int_ovrride = (EXT_PHY_SW_STATE(u, p) == NULL) ? 1 : 0;
   9971                 if (phy_addr == 0xff) {
   9972                     cli_out("Port %s: No %sPHY address assigned\n",
   9973                             SOC_PORT_NAME(u, p),
   9974                             intermediate ? "intermediate " : "");
   9975                     continue;
   9976                 }
   9977 #ifdef PORTMOD_SUPPORT
   9978             if (soc_feature(u, soc_feature_portmod)) {
   9979                 portmod_port_num_phys_get(u, p, &nof_phys);
   9980                 int_ovrride = 0;
   9981                 if (nof_phys == 1) {
   9982                     is_c45 = 0;
   9983                 } else {
   9984                     is_c45 = portmod_port_flags_test(u, p, PHY_FLAGS_C45);
   9985                 }
   9986             } else 
   9987 #endif
   9988             {
   9989                 is_c45 = soc_phy_is_c45_miim(u, p);
   9990             }
   9991                 if ( is_c45 && !intermediate && !int_ovrride) {
   9992                     for (i = 0; i < COUNTOF(p_devad); i++) {
   9993                         phy_devad = p_devad[i];
   9994                         cli_out("Port %s (PHY addr 0x%02x) "
   9995                                 "DevAd %d(%s) Reg 0x%04x: ",
   9996                                 SOC_PORT_NAME(u, p), phy_addr, phy_devad,
   9997                                 p_devad_str[i], phy_reg);
   9998 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT)
   9999                         if (1 == is_rcpu) {
  10000                             rv = soc_rcpu_miimc45_read(u, phy_addr,
  10001                                                        phy_devad, phy_reg,
  10002                                                        &phy_data);
  10003                         } else
  10004 #endif                          /* defined(BCM_RCPU_SUPPORT) && 
  10005                                    defined(BCM_CMICM_SUPPORT) */
  10006                         if (EXT_PHY_SW_STATE(u, p) &&
  10007                                 (EXT_PHY_SW_STATE(u, p)->read)) {
  10008                             rv = EXT_PHY_SW_STATE(u, p)->read(u, phy_addr,
  10009                                                               BCM_PORT_PHY_CLAUSE45_ADDR
  10010                                                               (phy_devad,
  10011                                                                phy_reg),
  10012                                                               &phy_data);
  10013                         } else if(soc_feature(u, soc_feature_portmod)) {
  10014                             rv = soc_miimc45_read(u, phy_addr,phy_devad, phy_reg, &phy_data);
  10015                         } else {
  10016                             rv = soc_miimc45_read(u, phy_addr,
  10017                                                   phy_devad, phy_reg,
  10018                                                   &phy_data);
  10019                         }
  10020 
  10021                         if (rv < 0) {
  10022                             cli_out("\nERROR: Port %s: "
  10023                                     "soc_miim_read failed: %s\n",
  10024                                     SOC_PORT_NAME(u, p), soc_errmsg(rv));
  10025 			    return CMD_FAIL;
  10026                         }
  10027                         var_set_hex("phy_reg_data", phy_data, TRUE, FALSE);
  10028                         cli_out("0x%04x\n", phy_data);
  10029                     }
  10030                 } else {
  10031                     cli_out("Port %s (PHY addr 0x%02x) Reg 0x%04x: ",
  10032                             SOC_PORT_NAME(u, p), phy_addr, phy_reg);
  10033 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT)
  10034                     if (1 == is_rcpu) {
  10035                         rv = soc_rcpu_miim_read(u, phy_addr, phy_reg,
  10036                                                 &phy_data);
  10037                     } else
  10038 #endif                          /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */
  10039                     if (!intermediate && !int_ovrride) {
  10040                         if (EXT_PHY_SW_STATE(u, p) &&
  10041                             (EXT_PHY_SW_STATE(u, p)->read)) {
  10042                             rv = EXT_PHY_SW_STATE(u, p)->read(u, phy_addr,
  10043                                                               phy_reg,
  10044                                                               &phy_data);
  10045                         } else if(soc_feature(u, soc_feature_portmod)) {
  10046 #ifdef PORTMOD_SUPPORT
  10047                             rv = portmod_port_phy_reg_read(u,p, -1, 0,phy_reg,&phy_data32);
  10048                             phy_data = (uint16)phy_data32;
  10049 #endif
  10050                         } else {
  10051                             rv = soc_miim_read(u, phy_addr, phy_reg, &phy_data);
  10052                         }
  10053                     } else {
  10054                         if (INT_PHY_SW_STATE(u, p) &&
  10055                             (INT_PHY_SW_STATE(u, p)->read)) {
  10056                             rv = INT_PHY_SW_STATE(u, p)->read(u, phy_addr,
  10057                                                               phy_reg,
  10058                                                               &phy_data);
  10059                         } else if(soc_feature(u, soc_feature_portmod)) {
  10060 #ifdef PORTMOD_SUPPORT
  10061                             rv = portmod_port_phy_reg_read(u,p, -1, 0,phy_reg,&phy_data32);
  10062                             phy_data = (uint16)phy_data32;
  10063 #endif
  10064                         } else {
  10065                             rv = soc_miim_read(u, phy_addr, phy_reg, &phy_data);
  10066                         }
  10067                     }
  10068 
  10069                     if (rv < 0) {
  10070                         cli_out("\nERROR: Port %s: soc_miim_read failed: %s\n",
  10071                                 SOC_PORT_NAME(u, p), soc_errmsg(rv));
  10072 			return CMD_FAIL;
  10073                     }
  10074                     var_set_hex("phy_reg_data", phy_data, TRUE, FALSE);
  10075                     cli_out("0x%04x\n", phy_data);
  10076                 }
  10077             }
  10078         } else {                /* set the reg to given value for the indicated phys */
  10079             c = ARG_GET(a);
  10080             phy_data = phy_devad = sal_ctoi(c, 0);
  10081 
  10082             DPORT_SOC_PBMP_ITER(u, pbm, dport, p) {
  10083                 phy_addr = (intermediate ?
  10084                             port_to_phyaddr_int(u, p) : port_to_phyaddr(u, p));
  10085                 int_ovrride = (EXT_PHY_SW_STATE(u, p) == NULL) ? 1 : 0;
  10086                 if (phy_addr == 0xff) {
  10087                     cli_out("Port %s: No %sPHY address assigned\n",
  10088                             SOC_PORT_NAME(u, p),
  10089                             intermediate ? "intermediate " : "");
  10090 		    return CMD_FAIL;
  10091                 }
  10092 #ifdef PORTMOD_SUPPORT
  10093                 if (soc_feature(u, soc_feature_portmod)) {
  10094                     portmod_port_num_phys_get(u, p, &nof_phys);
  10095                     int_ovrride = 0;
  10096                     if (nof_phys == 1) {
  10097                         is_c45 = 0;
  10098                     } else {
  10099                         is_c45 = portmod_port_flags_test(u, p, PHY_FLAGS_C45);
  10100                     }
  10101                 } else
  10102 #endif
  10103                 {
  10104                     is_c45 = soc_phy_is_c45_miim(u, p);
  10105                 }
  10106                 if ( is_c45 && !intermediate && !int_ovrride) {
  10107                     for (i = 0; i < COUNTOF(p_devad); i++) {
  10108                         if (phy_devad == p_devad[i]) {
  10109                             break;
  10110                         }
  10111                     }
  10112                     if (i >= COUNTOF(p_devad)) {
  10113                         cli_out("\nERROR: Port %s: Invalid DevAd %d\n",
  10114                                 SOC_PORT_NAME(u, p), phy_devad);
  10115 			return CMD_FAIL;
  10116                     }
  10117                     if (ARG_CNT(a) == 0) {/* no more args; show this register */
  10118                         cli_out("Port %s (PHY addr 0x%02x) "
  10119                                 "DevAd %d(%s) Reg 0x%04x: ",
  10120                                 SOC_PORT_NAME(u, p), phy_addr, phy_devad,
  10121                                 p_devad_str[i], phy_reg);
  10122 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT)
  10123                         if (1 == is_rcpu) {
  10124                             rv = soc_rcpu_miimc45_read(u, phy_addr,
  10125                                                        phy_devad, phy_reg,
  10126                                                        &phy_data);
  10127                         } else
  10128 #endif                          /* defined(BCM_RCPU_SUPPORT) &&
  10129                                    defined(BCM_CMICM_SUPPORT) */
  10130                         if (EXT_PHY_SW_STATE(u, p) &&
  10131                                 (EXT_PHY_SW_STATE(u, p)->read)) {
  10132                             rv = EXT_PHY_SW_STATE(u, p)->read(u, phy_addr,
  10133                                                               BCM_PORT_PHY_CLAUSE45_ADDR
  10134                                                               (phy_devad,
  10135                                                                phy_reg),
  10136                                                               &phy_data);
  10137                         } else if(soc_feature(u, soc_feature_portmod)) {
  10138                             rv = soc_miimc45_read(u, phy_addr,
  10139                                                   phy_devad, phy_reg,
  10140                                                   &phy_data);
  10141 
  10142                         } else {
  10143                             rv = soc_miimc45_read(u, phy_addr,
  10144                                                   phy_devad, phy_reg,
  10145                                                   &phy_data);
  10146                         }
  10147 
  10148                         if (rv < 0) {
  10149                             cli_out("\nERROR: Port %s: "
  10150                                     "soc_miim_read failed: %s\n",
  10151                                     SOC_PORT_NAME(u, p), soc_errmsg(rv));
  10152 			    return CMD_FAIL;
  10153                         }
  10154                         var_set_hex("phy_reg_data", phy_data, TRUE, FALSE);
  10155                         cli_out("0x%04x\n", phy_data);
  10156                     } else {    /* write */
  10157                         c = ARG_GET(a);
  10158                         phy_data = sal_ctoi(c, 0);
  10159 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT)
  10160                         if (1 == is_rcpu) {
  10161                             rv = soc_rcpu_miimc45_write(u, phy_addr,
  10162                                                         phy_devad, phy_reg,
  10163                                                         phy_data);
  10164                         } else
  10165 #endif                          /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */
  10166                         if (EXT_PHY_SW_STATE(u, p) &&
  10167                                 (EXT_PHY_SW_STATE(u, p)->write)) {
  10168                             rv = EXT_PHY_SW_STATE(u, p)->write(u, phy_addr,
  10169                                                                BCM_PORT_PHY_CLAUSE45_ADDR
  10170                                                                (phy_devad,
  10171                                                                 phy_reg),
  10172                                                                phy_data);
  10173                         } else if(soc_feature(u, soc_feature_portmod)) {
  10174 #ifdef PORTMOD_SUPPORT
  10175                             portmod_port_num_phys_get(u, p, &nof_phys);
  10176                             if(nof_phys > 1 ){
  10177                                 rv = soc_miimc45_write(u, phy_addr,
  10178                                                        phy_devad, phy_reg,
  10179                                                        phy_data);
  10180                             } else
  10181 #endif 
  10182                             {
  10183                                 rv = soc_sbus_mdio_write(u, phy_addr, phy_reg, phy_data);
  10184                             }
  10185                         } else {
  10186                             rv = soc_miimc45_write(u, phy_addr,
  10187                                                    phy_devad, phy_reg,
  10188                                                    phy_data);
  10189                         }
  10190 
  10191                         if (rv < 0) {
  10192                             cli_out("ERROR: Port %s: "
  10193                                     "soc_miim_write failed: %s\n",
  10194                                     SOC_PORT_NAME(u, p), soc_errmsg(rv));
  10195 			    return CMD_FAIL;
  10196                         }
  10197                     }
  10198                 } else {
  10199 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT)
  10200                     if (1 == is_rcpu) {
  10201                         rv = soc_rcpu_miim_write(u, phy_addr, phy_reg,
  10202                                                  phy_data);
  10203                     } else
  10204 #endif                          /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */
  10205                     if (!intermediate && !int_ovrride) {
  10206                         if (EXT_PHY_SW_STATE(u, p) &&
  10207                             (EXT_PHY_SW_STATE(u, p)->write)) {
  10208                             rv = EXT_PHY_SW_STATE(u, p)->write(u, phy_addr,
  10209                                                                phy_reg,
  10210                                                                phy_data);
  10211                         } else if(soc_feature(u, soc_feature_portmod)) {
  10212 #ifdef PORTMOD_SUPPORT
  10213                             portmod_port_num_phys_get(u, p, &nof_phys);
  10214                             if(nof_phys > 1 ){
  10215                                 rv = soc_miimc45_write(u, phy_addr,
  10216                                                        phy_devad, phy_reg,
  10217                                                        phy_data);
  10218                             } else {
  10219                                 rv = portmod_port_phy_reg_write(u, p, -1, 0, phy_reg, phy_data);
  10220                             }
  10221 #endif
  10222                         } else {
  10223                             rv = soc_miim_write(u, phy_addr, phy_reg, phy_data);
  10224                         }
  10225                     } else {
  10226                         if (INT_PHY_SW_STATE(u, p) &&
  10227                             (INT_PHY_SW_STATE(u, p)->write)) {
  10228                             rv = INT_PHY_SW_STATE(u, p)->write(u, phy_addr,
  10229                                                                phy_reg,
  10230                                                                phy_data);
  10231                         } else if(soc_feature(u, soc_feature_portmod)) {
  10232 #ifdef PORTMOD_SUPPORT
  10233                             rv = portmod_port_phy_reg_write(u, p, -1, 0, phy_reg, phy_data);
  10234 #endif
  10235                         } else {
  10236                             rv = soc_miim_write(u, phy_addr, phy_reg, phy_data);
  10237                         }
  10238                     }
  10239                     if (rv < 0) {
  10240                         cli_out("ERROR: Port %s: soc_miim_write failed: %s\n",
  10241                                 SOC_PORT_NAME(u, p), soc_errmsg(rv));
  10242 			return CMD_FAIL;
  10243                     }
  10244                 }
  10245             }
  10246         }
  10247     }
  10248 
  10249     if (BCM_FAILURE(rv)) {
  10250 	    cli_out("%s\n", bcm_errmsg(rv));
  10251 	    return CMD_FAIL;
  10252     }
  10253     return CMD_OK;
  10254 }
  10255 
  10256 /***********************************************************************
  10257  *
  10258  * Combo port support
  10259  */
  10260 
  10261 /*
  10262  * Function:    if_combo_dump
  10263  * Purpose:     Dump the contents of a bcm_phy_config_t
  10264  */
  10265 
  10266 STATIC int
  10267 if_combo_dump(args_t *a, int u, int p, int medium)
  10268 {
  10269     char pm_str[80];
  10270     bcm_port_medium_t active_medium;
  10271     int r;
  10272     bcm_phy_config_t cfg;
  10273 
  10274     /*
  10275      * Get active medium so we can put an asterisk next to the status if
  10276      * it is active.
  10277      */
  10278 
  10279     if ((r = bcm_port_medium_get(u, p, &active_medium)) < 0) {
  10280         return r;
  10281     }
  10282     if ((r = bcm_port_medium_config_get(u, p, medium, &cfg)) < 0) {
  10283         return r;
  10284     }
  10285 
  10286     cli_out("%s:\t%s medium%s\n",
  10287             BCM_PORT_NAME(u, p),
  10288             MEDIUM_STATUS(medium), (medium == active_medium) ? " (active)" : "");
  10289 
  10290     format_port_mode(pm_str, sizeof(pm_str), cfg.autoneg_advert, TRUE);
  10291 
  10292     cli_out("\tenable=%d preferred=%d "
  10293             "force_speed=%d force_duplex=%d master=%s\n",
  10294             cfg.enable, cfg.preferred,
  10295             cfg.force_speed, cfg.force_duplex, PHYMASTER_MODE(cfg.master));
  10296     cli_out("\tautoneg_enable=%d autoneg_advert=%s(0x%x)\n",
  10297             cfg.autoneg_enable, pm_str, cfg.autoneg_advert);
  10298     cli_out("\tMDIX=%s\n", MDIX_MODE(cfg.mdix));
  10299 
  10300     return BCM_E_NONE;
  10301 }
  10302 
  10303 static int combo_watch[SOC_MAX_NUM_DEVICES][SOC_MAX_NUM_PORTS];
  10304 
  10305 static void
  10306 if_combo_watch(int unit, bcm_port_t port, bcm_port_medium_t medium, void *arg)
  10307 {
  10308     cli_out("Unit %d: %s: Active medium switched to %s\n",
  10309             unit, BCM_PORT_NAME(unit, port), MEDIUM_STATUS(medium));
  10310 
  10311     /* 
  10312      * Increment the number of medium changes. Remember, that we pass the 
  10313      * address of combo_watch[unit][port] when we register this callback
  10314      */
  10315     (*((int *)arg))++;
  10316 }
  10317 
  10318 /*
  10319  * Function:    if_combo
  10320  * Purpose:     Control combo ports
  10321  * Parameters:  u - SOC unit #
  10322  *              a - pointer to args
  10323  * Returns:     CMD_OK/CMD_FAIL/
  10324  */
  10325 cmd_result_t
  10326 if_esw_combo(int u, args_t *a)
  10327 {
  10328     pbmp_t pbm;
  10329     soc_port_t p, dport;
  10330     int specified_medium = BCM_PORT_MEDIUM_COUNT;
  10331     int r, rc, rf;
  10332     char *c;
  10333     parse_table_t pt;
  10334     bcm_phy_config_t cfg, cfg_opt;
  10335 
  10336     enum if_combo_cmd_e {
  10337         COMBO_CMD_DUMP,
  10338         COMBO_CMD_SET,
  10339         COMBO_CMD_WATCH,
  10340         CONBO_CMD_COUNT
  10341     } cmd;
  10342 
  10343     enum if_combo_watch_arg_e {
  10344         COMBO_CMD_WATCH_SHOW,
  10345         COMBO_CMD_WATCH_ON,
  10346         COMBO_CMD_WATCH_OFF,
  10347         COMBO_CMD_WATCH_COUNT
  10348     } watch_arg = COMBO_CMD_WATCH_SHOW;
  10349 
  10350     cfg_opt.enable = -1;
  10351     cfg_opt.preferred = -1;
  10352     cfg_opt.autoneg_enable = -1;
  10353     cfg_opt.autoneg_advert = 0xffffffff;
  10354     cfg_opt.force_speed = -1;
  10355     cfg_opt.force_duplex = -1;
  10356     cfg_opt.master = -1;
  10357     cfg_opt.mdix = -1;
  10358 
  10359     if (!sh_check_attached(ARG_CMD(a), u)) {
  10360         return CMD_FAIL;
  10361     }
  10362 
  10363     if ((c = ARG_GET(a)) == NULL) {
  10364         return CMD_USAGE;
  10365     }
  10366 
  10367     if (parse_bcm_pbmp(u, c, &pbm) < 0) {
  10368         cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c);
  10369         return CMD_FAIL;
  10370     }
  10371 
  10372     SOC_PBMP_AND(pbm, PBMP_PORT_ALL(u));
  10373 
  10374     c = ARG_GET(a);             /* NULL or media type or command */
  10375 
  10376     if (c == NULL) {
  10377         cmd = COMBO_CMD_DUMP;
  10378         specified_medium = BCM_PORT_MEDIUM_COUNT;
  10379     } else if (sal_strcasecmp(c, "copper") == 0 || sal_strcasecmp(c, "c") == 0) {
  10380         cmd = COMBO_CMD_SET;
  10381         specified_medium = BCM_PORT_MEDIUM_COPPER;
  10382     } else if (sal_strcasecmp(c, "fiber") == 0 || sal_strcasecmp(c, "f") == 0) {
  10383         cmd = COMBO_CMD_SET;
  10384         specified_medium = BCM_PORT_MEDIUM_FIBER;
  10385     } else if (sal_strcasecmp(c, "watch") == 0 || sal_strcasecmp(c, "w") == 0) {
  10386         cmd = COMBO_CMD_WATCH;
  10387     } else {
  10388         return CMD_USAGE;
  10389     }
  10390 
  10391     switch (cmd) {
  10392         case COMBO_CMD_SET:
  10393             if ((c = ARG_CUR(a)) != NULL) {
  10394                 if (c[0] == '=') {
  10395                     return CMD_USAGE;   /* '=' unsupported */
  10396                 }
  10397 
  10398                 parse_table_init(u, &pt);
  10399                 parse_table_add(&pt, "Enable", PQ_DFL | PQ_BOOL, 0,
  10400                                 &cfg_opt.enable, 0);
  10401                 parse_table_add(&pt, "PREFerred", PQ_DFL | PQ_BOOL, 0,
  10402                                 &cfg_opt.preferred, 0);
  10403                 parse_table_add(&pt, "Autoneg_Enable", PQ_DFL | PQ_BOOL, 0,
  10404                                 &cfg_opt.autoneg_enable, 0);
  10405                 parse_table_add(&pt, "Autoneg_Advert", PQ_DFL | PQ_PORTMODE, 0,
  10406                                 &cfg_opt.autoneg_advert, 0);
  10407                 parse_table_add(&pt, "Force_Speed", PQ_DFL | PQ_INT, 0,
  10408                                 &cfg_opt.force_speed, 0);
  10409                 parse_table_add(&pt, "Force_Duplex", PQ_DFL | PQ_BOOL, 0,
  10410                                 &cfg_opt.force_duplex, 0);
  10411                 parse_table_add(&pt, "MAster", PQ_DFL | PQ_BOOL, 0,
  10412                                 &cfg_opt.master, 0);
  10413                 parse_table_add(&pt, "MDIX", PQ_DFL | PQ_MULTI, 0,
  10414                                 &cfg_opt.mdix, mdix_mode);
  10415 
  10416                 if (parse_arg_eq(a, &pt) < 0) {
  10417                     parse_arg_eq_done(&pt);
  10418                     return CMD_USAGE;
  10419                 }
  10420                 parse_arg_eq_done(&pt);
  10421 
  10422                 if (ARG_CUR(a) != NULL) {
  10423                     return CMD_USAGE;
  10424                 }
  10425             } else {
  10426                 cmd = COMBO_CMD_DUMP;
  10427             }
  10428 
  10429             break;
  10430 
  10431         case COMBO_CMD_WATCH:
  10432             c = ARG_GET(a);
  10433 
  10434             if (c == NULL) {
  10435                 watch_arg = COMBO_CMD_WATCH_SHOW;
  10436             } else if (sal_strcasecmp(c, "on") == 0) {
  10437                 watch_arg = COMBO_CMD_WATCH_ON;
  10438             } else if (sal_strcasecmp(c, "off") == 0) {
  10439                 watch_arg = COMBO_CMD_WATCH_OFF;
  10440             } else {
  10441                 return CMD_USAGE;
  10442             }
  10443             break;
  10444 
  10445         default:
  10446             break;
  10447     }
  10448 
  10449     /* coverity[overrun-local] */
  10450     DPORT_BCM_PBMP_ITER(u, pbm, dport, p) {
  10451         switch (cmd) {
  10452             case COMBO_CMD_DUMP:
  10453                 cli_out("Port %s:\n", BCM_PORT_NAME(u, p));
  10454 
  10455                 rc = rf = BCM_E_UNAVAIL;
  10456                 if (specified_medium == BCM_PORT_MEDIUM_COPPER ||
  10457                     specified_medium == BCM_PORT_MEDIUM_COUNT) {
  10458                     rc = if_combo_dump(a, u, p, BCM_PORT_MEDIUM_COPPER);
  10459                     if (rc != BCM_E_NONE && rc != BCM_E_UNAVAIL) {
  10460                         cli_out("%s:\tERROR(copper): %s\n",
  10461                                 BCM_PORT_NAME(u, p), bcm_errmsg(rc));
  10462                     }
  10463                 }
  10464 
  10465                 if (specified_medium == BCM_PORT_MEDIUM_FIBER ||
  10466                     specified_medium == BCM_PORT_MEDIUM_COUNT) {
  10467                     rf = if_combo_dump(a, u, p, BCM_PORT_MEDIUM_FIBER);
  10468                     if (rf != BCM_E_NONE && rf != BCM_E_UNAVAIL) {
  10469                         cli_out("%s:\tERROR(fiber): %s\n",
  10470                                 BCM_PORT_NAME(u, p), bcm_errmsg(rf));
  10471                     }
  10472                 }
  10473 
  10474                 /*
  10475                  * If there were problems getting medium-specific info on 
  10476                  * individual mediums, then they will be printed above. However,
  10477                  * if BCM_E_UNAVAIL is returned for both copper and fiber mediums
  10478                  * we'll print only one error message
  10479                  */
  10480                 if (rc == BCM_E_UNAVAIL && rf == BCM_E_UNAVAIL) {
  10481                     cli_out("%s:\tmedium info unavailable\n",
  10482                             BCM_PORT_NAME(u, p));
  10483                 }
  10484                 break;
  10485 
  10486             case COMBO_CMD_SET:
  10487                 /*
  10488                  * Update the medium operating mode.
  10489                  */
  10490                 r = bcm_port_medium_config_get(u, p, specified_medium, &cfg);
  10491 
  10492                 if (r < 0) {
  10493                     cli_out("%s: port %s: Error getting medium config: %s\n",
  10494                             ARG_CMD(a), BCM_PORT_NAME(u, p), bcm_errmsg(r));
  10495                     return CMD_FAIL;
  10496                 }
  10497 
  10498                 if (cfg_opt.enable != -1) {
  10499                     cfg.enable = cfg_opt.enable;
  10500                 }
  10501 
  10502                 if (cfg_opt.preferred != -1) {
  10503                     cfg.preferred = cfg_opt.preferred;
  10504                 }
  10505 
  10506                 if (cfg_opt.autoneg_enable != -1) {
  10507                     cfg.autoneg_enable = cfg_opt.autoneg_enable;
  10508                 }
  10509 
  10510                 if (cfg_opt.autoneg_advert != 0xffffffff) {
  10511                     cfg.autoneg_advert = cfg_opt.autoneg_advert;
  10512                 }
  10513 
  10514                 if (cfg_opt.force_speed != -1) {
  10515                     cfg.force_speed = cfg_opt.force_speed;
  10516                 }
  10517 
  10518                 if (cfg_opt.force_duplex != -1) {
  10519                     cfg.force_duplex = cfg_opt.force_duplex;
  10520                 }
  10521 
  10522                 if (cfg_opt.master != -1) {
  10523                     cfg.master = cfg_opt.master;
  10524                 }
  10525 
  10526                 if (cfg_opt.mdix != -1) {
  10527                     cfg.mdix = cfg_opt.mdix;
  10528                 }
  10529 
  10530                 r = bcm_port_medium_config_set(u, p, specified_medium, &cfg);
  10531 
  10532                 if (r < 0) {
  10533                     cli_out("%s: port %s: Error setting medium config: %s\n",
  10534                             ARG_CMD(a), BCM_PORT_NAME(u, p), bcm_errmsg(r));
  10535                     return CMD_FAIL;
  10536                 }
  10537 
  10538                 break;
  10539 
  10540             case COMBO_CMD_WATCH:
  10541                 switch (watch_arg) {
  10542                     case COMBO_CMD_WATCH_SHOW:
  10543                         if (combo_watch[u][p]) {
  10544                             cli_out("Port %s: Medium status "
  10545                                     "change watch is  ON. "
  10546                                     "Medim changed %d times\n",
  10547                                     BCM_PORT_NAME(u, p),
  10548                                     combo_watch[u][p] - 1);
  10549                         } else {
  10550                             cli_out("Port %s: Medium status "
  10551                                     "change watch is OFF.\n",
  10552                                     BCM_PORT_NAME(u, p));
  10553                         }
  10554                         break;
  10555 
  10556                     case COMBO_CMD_WATCH_ON:
  10557                         if (!combo_watch[u][p]) {
  10558                             r = bcm_port_medium_status_register(u, p,
  10559                                                                 if_combo_watch,
  10560                                                                 &combo_watch[u]
  10561                                                                 [p]);
  10562                             if (r < 0) {
  10563                                 cli_out("Error registerinig medium "
  10564                                         "status change callback for %s: %s\n",
  10565                                         BCM_PORT_NAME(u, p),
  10566                                         soc_errmsg(r));
  10567                                 return (CMD_FAIL);
  10568                             }
  10569 
  10570                             combo_watch[u][p] = 1;
  10571                         }
  10572 
  10573                         cli_out("Port %s: Medium change watch is ON\n",
  10574                                 BCM_PORT_NAME(u, p));
  10575 
  10576                         break;
  10577 
  10578                     case COMBO_CMD_WATCH_OFF:
  10579                         if (combo_watch[u][p]) {
  10580                             r = bcm_port_medium_status_unregister(u, p,
  10581                                                                   if_combo_watch,
  10582                                                                   &combo_watch
  10583                                                                   [u][p]);
  10584                             if (r < 0) {
  10585                                 cli_out("Error unregisterinig medium "
  10586                                         "status change callback for %s: %s\n",
  10587                                         BCM_PORT_NAME(u, p),
  10588                                         soc_errmsg(r));
  10589                                 return (CMD_FAIL);
  10590                             }
  10591 
  10592                             combo_watch[u][p] = 0;
  10593                         }
  10594 
  10595                         cli_out("Port %s: Medium change watch is OFF\n",
  10596                                 BCM_PORT_NAME(u, p));
  10597 
  10598                         break;
  10599 
  10600                     default:
  10601                         return CMD_FAIL;
  10602                 } /* switch ( watch_arg ) */
  10603 
  10604                 break;
  10605 
  10606             /* must default. for covering all the cases of 'enum if_combo_cmd_e' */
  10607             /* coverity[dead_error_begin : FALSE] */
  10608             default:
  10609                 return CMD_FAIL;
  10610         }  /* switch ( cmd ) */
  10611     }
  10612 
  10613     return CMD_OK;
  10614 }
  10615 
  10616 /*
  10617  * Function:
  10618  *    cmd_cablediag
  10619  * Purpose:
  10620  *    Run cable diagnostics (if available)
  10621  */
  10622 
  10623 cmd_result_t
  10624 cmd_esw_cablediag(int unit, args_t *a)
  10625 {
  10626     char *s;
  10627     bcm_pbmp_t pbm;
  10628     bcm_port_t port, dport;
  10629     int rv, i;
  10630     bcm_port_cable_diag_t cd;
  10631     char *statename[] = _SHR_PORT_CABLE_STATE_NAMES_INITIALIZER;
  10632 
  10633     if (!sh_check_attached(ARG_CMD(a), unit)) {
  10634         return CMD_FAIL;
  10635     }
  10636 
  10637     if ((s = ARG_GET(a)) == NULL) {
  10638         return CMD_USAGE;
  10639     }
  10640 
  10641     if (parse_bcm_pbmp(unit, s, &pbm) < 0) {
  10642         cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), s);
  10643         return CMD_FAIL;
  10644     }
  10645 
  10646     sal_memset(&cd, 0, sizeof(bcm_port_cable_diag_t));
  10647 
  10648     /* Coverity
  10649      * DPORT_BCM_PBMP_ITER checks that dport is valid.
  10650      */
  10651     /* coverity[overrun-local] */
  10652     DPORT_BCM_PBMP_ITER(unit, pbm, dport, port) {
  10653         rv = bcm_port_cable_diag(unit, port, &cd);
  10654         if (rv < 0) {
  10655             cli_out("%s: ERROR: port %s: %s\n",
  10656                     ARG_CMD(a), BCM_PORT_NAME(unit, port), bcm_errmsg(rv));
  10657             continue;
  10658         }
  10659         if (cd.fuzz_len == 0) {
  10660             cli_out("port %s: cable (%d pairs)\n",
  10661                     BCM_PORT_NAME(unit, port), cd.npairs);
  10662         } else {
  10663             cli_out("port %s: cable (%d pairs, length +/- %d meters)\n",
  10664                     BCM_PORT_NAME(unit, port), cd.npairs, cd.fuzz_len);
  10665         }
  10666         for (i = 0; i < cd.npairs; i++) {
  10667             cli_out("\tpair %c %s, length %d meters\n",
  10668                     'A' + i, statename[cd.pair_state[i]], cd.pair_len[i]);
  10669         }
  10670     }
  10671 
  10672     return CMD_OK;
  10673 }
  10674 
  10675 #ifdef BCM_XGS3_SWITCH_SUPPORT
  10676 /* XAUI BERT Test */
  10677 
  10678 char cmd_xaui_usage[] =
  10679     "Run XAUI BERT.\n"
  10680     "Usages:\n\t"
  10681     "  xaui bert SrcPort=<port> DestPort=<port> Duration=<usec> Verb=0/1\n";
  10682 
  10683 #define XAUI_PREEMPHASIS_MIN  (0)
  10684 #define XAUI_PREEMPHASIS_MAX  (15)
  10685 #define XAUI_IDRIVER_MIN      (0)
  10686 #define XAUI_IDRIVER_MAX      (15)
  10687 #define XAUI_EQUALIZER_MIN    (0)
  10688 #define XAUI_EQUALIZER_MAX    (7)
  10689 
  10690 typedef struct _xaui_bert_info_s {
  10691     bcm_port_t src_port;
  10692     bcm_port_t dst_port;
  10693     soc_xaui_config_t src_config;
  10694     soc_xaui_config_t dst_config;
  10695     soc_xaui_config_t test_config;
  10696     bcm_port_info_t src_info;
  10697     bcm_port_info_t dst_info;
  10698     int duration;
  10699     int linkscan_us;
  10700     int verbose;
  10701 } _xaui_bert_info_t;
  10702 
  10703 /*
  10704  * Function:
  10705  *      _xaui_bert_counter_check 
  10706  * Purpose:
  10707  *      Check BERT counters after the test. 
  10708  * Parameters:
  10709  *      (IN) unit       - BCM unit number
  10710  *      (IN) test_info - Test configuration 
  10711  * Returns:
  10712  *      BCM_E_NONE - success
  10713  *      BCM_E_XXXX - failed.
  10714  * Notes:
  10715  */
  10716 static int
  10717 _xaui_bert_counter_check(int unit, _xaui_bert_info_t *test_info)
  10718 {
  10719     bcm_port_t src_port, dst_port;
  10720     uint32 tx_pkt, tx_byte, rx_pkt, rx_byte, bit_err, byte_err, pkt_err;
  10721     int prbs_lock, lock;
  10722 
  10723     src_port = test_info->src_port;
  10724     dst_port = test_info->dst_port;
  10725 
  10726     /* Read Tx counters */
  10727     SOC_IF_ERROR_RETURN(soc_xaui_txbert_pkt_count_get(unit, src_port, &tx_pkt));
  10728     SOC_IF_ERROR_RETURN
  10729         (soc_xaui_txbert_byte_count_get(unit, src_port, &tx_byte));
  10730 
  10731     lock = 1;
  10732     /* Read Rx counters */
  10733     SOC_IF_ERROR_RETURN
  10734         (soc_xaui_rxbert_pkt_count_get(unit, dst_port, &rx_pkt, &prbs_lock));
  10735     lock &= prbs_lock;
  10736 
  10737     SOC_IF_ERROR_RETURN
  10738         (soc_xaui_rxbert_byte_count_get(unit, dst_port, &rx_byte, &prbs_lock));
  10739     lock &= prbs_lock;
  10740 
  10741     SOC_IF_ERROR_RETURN
  10742         (soc_xaui_rxbert_bit_err_count_get(unit, dst_port,
  10743                                            &bit_err, &prbs_lock));
  10744     lock &= prbs_lock;
  10745 
  10746     SOC_IF_ERROR_RETURN
  10747         (soc_xaui_rxbert_byte_err_count_get(unit, dst_port,
  10748                                             &byte_err, &prbs_lock));
  10749     lock &= prbs_lock;
  10750 
  10751     SOC_IF_ERROR_RETURN
  10752         (soc_xaui_rxbert_pkt_err_count_get(unit, dst_port,
  10753                                            &pkt_err, &prbs_lock));
  10754     lock &= prbs_lock;
  10755 
  10756     if (test_info->verbose) {
  10757         cli_out(" %4s->%4s, 0x%08x, 0x%08x, 0x%08x, %s, ",
  10758                 BCM_PORT_NAME(unit, src_port), BCM_PORT_NAME(unit, dst_port),
  10759                 tx_byte, rx_byte, bit_err, lock ? "       OK" : "      !OK");
  10760     }
  10761 
  10762     /* Check TX/RX counters */
  10763     if ((tx_byte == 0) || (tx_pkt == 0) ||
  10764         (tx_byte != rx_byte) || (tx_pkt != rx_pkt) || !lock) {
  10765         return BCM_E_FAIL;
  10766     }
  10767 
  10768     /* Check error counters */
  10769     if ((bit_err != 0) || (byte_err != 0) || (pkt_err != 0)) {
  10770         return BCM_E_FAIL;
  10771     }
  10772 
  10773     return BCM_E_NONE;
  10774 }
  10775 
  10776 /*
  10777  * Function:
  10778  *      _xaui_bert_test 
  10779  * Purpose:
  10780  *      Run BERT test with requested port configuration. 
  10781  * Parameters:
  10782  *      (IN) unit       - BCM unit number
  10783  *      (IN) test_info - Test configuration 
  10784  * Returns:
  10785  *      BCM_E_NONE - success
  10786  *      BCM_E_XXXX - failed.
  10787  * Notes:
  10788  */
  10789 static int
  10790 _xaui_bert_test(int unit, _xaui_bert_info_t *test_info)
  10791 {
  10792     int result1, result2;
  10793     bcm_port_t src_port, dst_port;
  10794 
  10795     src_port = test_info->src_port;
  10796     dst_port = test_info->dst_port;
  10797 
  10798     BCM_IF_ERROR_RETURN(bcm_port_speed_set(unit, src_port, 10000));
  10799     BCM_IF_ERROR_RETURN(bcm_port_speed_set(unit, dst_port, 10000));
  10800 
  10801     BCM_IF_ERROR_RETURN
  10802         (soc_xaui_config_set(unit, src_port, &test_info->test_config));
  10803     BCM_IF_ERROR_RETURN
  10804         (soc_xaui_config_set(unit, dst_port, &test_info->test_config));
  10805 
  10806     /* Wait up to 0.1 sec for TX PLL lock */
  10807     sal_usleep(100000);
  10808 
  10809     /* Enable RX BERT on both ports first */
  10810     BCM_IF_ERROR_RETURN(soc_xaui_rxbert_enable(unit, dst_port, TRUE));
  10811     if (src_port != dst_port) {
  10812         BCM_IF_ERROR_RETURN(soc_xaui_rxbert_enable(unit, src_port, TRUE));
  10813     }
  10814 
  10815     /* Enable TX BERT on both ports */
  10816     BCM_IF_ERROR_RETURN(soc_xaui_txbert_enable(unit, src_port, TRUE));
  10817     if (src_port != dst_port) {
  10818         BCM_IF_ERROR_RETURN(soc_xaui_txbert_enable(unit, dst_port, TRUE));
  10819     }
  10820 
  10821     /* Run test for requested duration */
  10822     sal_usleep(test_info->duration);
  10823 
  10824     /* Disable TX BERT */
  10825     BCM_IF_ERROR_RETURN(soc_xaui_txbert_enable(unit, src_port, FALSE));
  10826     if (src_port != dst_port) {
  10827         BCM_IF_ERROR_RETURN(soc_xaui_txbert_enable(unit, dst_port, FALSE));
  10828     }
  10829 
  10830     /* Give enough time to complete tx/rx */
  10831     sal_usleep(500);
  10832     result1 = _xaui_bert_counter_check(unit, test_info);
  10833     result2 = _xaui_bert_counter_check(unit, test_info);
  10834     if (BCM_SUCCESS(result1) && BCM_SUCCESS(result2)) {
  10835         cli_out(" ( P ) ");
  10836     } else {
  10837         cli_out(" ( F ) ");
  10838     }
  10839 
  10840     if (test_info->verbose) {
  10841         cli_out("\n");
  10842     }
  10843 
  10844     /* Disable RX BERT only after reading the counter. 
  10845      * Otherwise, counters always read zero.
  10846      */
  10847     BCM_IF_ERROR_RETURN(soc_xaui_rxbert_enable(unit, src_port, FALSE));
  10848     if (src_port != dst_port) {
  10849         BCM_IF_ERROR_RETURN(soc_xaui_rxbert_enable(unit, dst_port, FALSE));
  10850     }
  10851 
  10852     if ((BCM_E_NONE != result1) && (BCM_E_FAIL != result1)) {
  10853         return result1;
  10854     }
  10855     if ((BCM_E_NONE != result2) && (BCM_E_FAIL != result2)) {
  10856         return result2;
  10857     }
  10858     return BCM_E_NONE;
  10859 }
  10860 
  10861 /*
  10862  * Function:
  10863  *      _xaui_bert_save_config 
  10864  * Purpose:
  10865  *      Disable linkscan and save current port configuration. 
  10866  * Parameters:
  10867  *      (IN) unit       - BCM unit number
  10868  *      (OUT) test_info - Current port configuration 
  10869  * Returns:
  10870  *      BCM_E_NONE - success
  10871  *      BCM_E_XXXX - failed.
  10872  * Notes:
  10873  */
  10874 static int
  10875 _xaui_bert_save_config(int unit, _xaui_bert_info_t *test_info)
  10876 {
  10877 
  10878     /* If linkscan is enabled, disable linkscan */
  10879     BCM_IF_ERROR_RETURN(bcm_linkscan_enable_get(unit, &test_info->linkscan_us));
  10880     if (test_info->linkscan_us != 0) {
  10881         BCM_IF_ERROR_RETURN(bcm_linkscan_enable_set(unit, 0));
  10882         /* Give enough time for linkscan task to exit. */
  10883         sal_usleep(test_info->linkscan_us * 5);
  10884     }
  10885 
  10886     /* Save current settings */
  10887     BCM_IF_ERROR_RETURN
  10888         (soc_xaui_config_get(unit, test_info->src_port,
  10889                              &test_info->src_config));
  10890     BCM_IF_ERROR_RETURN
  10891         (soc_xaui_config_get(unit, test_info->dst_port,
  10892                              &test_info->dst_config));
  10893 
  10894     /* Save original speed settings */
  10895     BCM_IF_ERROR_RETURN
  10896         (bcm_port_info_save(unit, test_info->src_port, &test_info->src_info));
  10897     BCM_IF_ERROR_RETURN
  10898         (bcm_port_info_save(unit, test_info->dst_port, &test_info->dst_info));
  10899 
  10900     return BCM_E_NONE;
  10901 }
  10902 
  10903 /*
  10904  * Function:
  10905  *      _xaui_bert_restore_config 
  10906  * Purpose:
  10907  *      Restore original port configuration. 
  10908  * Parameters:
  10909  *      (IN) unit      - BCM unit number
  10910  *      (IN) test_info - Port configuration to be restored 
  10911  * Returns:
  10912  *      BCM_E_NONE - success
  10913  *      BCM_E_XXXX - failed.
  10914  * Notes:
  10915  */
  10916 static int
  10917 _xaui_bert_restore_config(int unit, _xaui_bert_info_t *test_info)
  10918 {
  10919 
  10920     BCM_IF_ERROR_RETURN
  10921         (bcm_port_info_restore(unit, test_info->src_port,
  10922                                &test_info->src_info));
  10923     BCM_IF_ERROR_RETURN
  10924         (bcm_port_info_restore(unit, test_info->dst_port,
  10925                                &test_info->dst_info));
  10926 
  10927 #if 0
  10928     /* Restore original configuration */
  10929     BCM_IF_ERROR_RETURN
  10930         (soc_xaui_config_set(unit, test_info->src_port,
  10931                              &test_info->src_config));
  10932     BCM_IF_ERROR_RETURN
  10933         (soc_xaui_config_set(unit, test_info->dst_port,
  10934                              &test_info->dst_config));
  10935 #endif
  10936 
  10937     if (test_info->linkscan_us != 0) {
  10938         BCM_IF_ERROR_RETURN
  10939             (bcm_linkscan_enable_set(unit, test_info->linkscan_us));
  10940     }
  10941 
  10942     return BCM_E_NONE;
  10943 }
  10944 
  10945 char bert_header[] =
  10946     "                                   Equalizer\n"
  10947     "I_Driver     0      1      2      3      4      5      6      7\n";
  10948 
  10949 char bert_header_v[] =
  10950     "\n Preemph, I_Driver, Equalizer,   Src->Des,"
  10951     "    tx_byte,    rx_byte,    bit_err, PRBS Lock,"
  10952     "    Des->Src,    tx_byte,    rx_byte,    bit_err," " PRBS Lock\n";
  10953 
  10954 /*
  10955  * Function:
  10956  *      cmd_xaui 
  10957  * Purpose:
  10958  *      Entry point to XAUI related CLI commands.
  10959  * Parameters:
  10960  *      (IN) unit - BCM unit number
  10961  *      (IN) a    - Arguments for the command 
  10962  * Returns:
  10963  *      BCM_E_NONE - success
  10964  *      BCM_E_XXXX - failed.
  10965  * Notes:
  10966  */
  10967 cmd_result_t
  10968 cmd_xaui(int unit, args_t *a)
  10969 {
  10970     char *subcmd;
  10971     parse_table_t pt;
  10972     int rv;
  10973     cmd_result_t retCode;
  10974 
  10975     if (!sh_check_attached(ARG_CMD(a), unit)) {
  10976         return CMD_FAIL;
  10977     }
  10978 
  10979     if ((subcmd = ARG_GET(a)) == NULL) {
  10980         return CMD_USAGE;
  10981     }
  10982 
  10983     rv = BCM_E_NONE;
  10984     if (sal_strcasecmp(subcmd, "bert") == 0) {
  10985         uint32 preemphasis, idriver, equalizer;
  10986         _xaui_bert_info_t test_info;
  10987 
  10988         sal_memset(&test_info, 0, sizeof(test_info));
  10989         test_info.duration = 10;
  10990 
  10991         parse_table_init(unit, &pt);
  10992         parse_table_add(&pt, "SrcPort", PQ_DFL | PQ_PORT, 0,
  10993                         &test_info.src_port, NULL);
  10994         parse_table_add(&pt, "DestPort", PQ_DFL | PQ_PORT, 0,
  10995                         &test_info.dst_port, NULL);
  10996         parse_table_add(&pt, "Duration", PQ_INT | PQ_DFL, 0,
  10997                         &test_info.duration, NULL);
  10998         parse_table_add(&pt, "Verbose", PQ_BOOL | PQ_DFL, 0,
  10999                         &test_info.verbose, NULL);
  11000 
  11001         if (!parseEndOk(a, &pt, &retCode)) {
  11002             return retCode;
  11003         }
  11004 
  11005         /* Run only on HG and XE port */
  11006         if ((!IS_HG_PORT(unit, test_info.src_port) &&
  11007              !IS_XE_PORT(unit, test_info.src_port)) ||
  11008             (!IS_HG_PORT(unit, test_info.dst_port) &&
  11009              !IS_XE_PORT(unit, test_info.dst_port))) {
  11010             cli_out("%s: ERROR: Invalid port selection %d, %d\n",
  11011                     ARG_CMD(a), test_info.src_port, test_info.dst_port);
  11012             return CMD_FAIL;
  11013         }
  11014 
  11015         if ((rv = _xaui_bert_save_config(unit, &test_info)) < 0) {
  11016             goto cmd_xaui_err;
  11017         }
  11018 
  11019         test_info.test_config = test_info.src_config;
  11020         for (preemphasis = XAUI_PREEMPHASIS_MIN;
  11021              preemphasis <= XAUI_PREEMPHASIS_MAX; preemphasis++) {
  11022             test_info.test_config.preemphasis = preemphasis;
  11023 
  11024             if (!test_info.verbose) {
  11025                 cli_out("\nPreemphasis = %d\n", preemphasis);
  11026             }
  11027 
  11028             cli_out("%s", test_info.verbose ? bert_header_v : bert_header);
  11029 
  11030             for (idriver = XAUI_IDRIVER_MIN;
  11031                  idriver <= XAUI_IDRIVER_MAX; idriver++) {
  11032                 test_info.test_config.idriver = idriver;
  11033                 if (!test_info.verbose) {
  11034                     cli_out("%8d  ", idriver);
  11035                 }
  11036                 for (equalizer = XAUI_EQUALIZER_MIN;
  11037                      equalizer <= XAUI_EQUALIZER_MAX; equalizer++) {
  11038 
  11039                     if (test_info.verbose) {
  11040                         cli_out("%8d, %8d, %9d,", preemphasis, idriver,
  11041                                 equalizer);
  11042                     }
  11043 
  11044                     test_info.test_config.equalizer_ctrl = equalizer;
  11045                     if ((rv = _xaui_bert_test(unit, &test_info)) < 0) {
  11046                         _xaui_bert_restore_config(unit, &test_info);
  11047                         goto cmd_xaui_err;
  11048                     }
  11049                 }
  11050                 cli_out("\n");
  11051             }
  11052         }
  11053 
  11054         if ((rv = _xaui_bert_restore_config(unit, &test_info)) < 0) {
  11055             goto cmd_xaui_err;
  11056         }
  11057         return CMD_OK;
  11058     }
  11059     cli_out("%s: ERROR: Unknown xaui subcommand: %s\n", ARG_CMD(a), subcmd);
  11060     return CMD_USAGE;
  11061 
  11062  cmd_xaui_err:
  11063     cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv));
  11064     return CMD_FAIL;
  11065 }
  11066 #endif                          /* BCM_XGS3_SWITCH_SUPPORT */
  11067 
  11068 #if defined(INCLUDE_FCMAP)
  11069 /* BFCMAP TEST */
  11070 int
  11071 diag_bfcmap_pcfg_set_get(int port)
  11072 {
  11073     int rc = CMD_OK;
  11074 
  11075     rc = bfcmap_pcfg_set_get(port);
  11076 
  11077     return (rc == BFCMAP_E_NONE) ? CMD_OK : CMD_FAIL;
  11078 }
  11079 
  11080 int bfcmap88060_show_fc_config(int unit, int port)
  11081 {
  11082     int rv = CMD_OK;
  11083     bcm_fcmap_port_config_t pCfg;
  11084 
  11085     /* Setting cos to invalid COS value to
  11086      * get current configured cos and priority value
  11087      */
  11088     pCfg.cos_to_pri.cos = 0xFFFF;
  11089 
  11090     rv = bcm_fcmap_port_config_get(unit, port, &pCfg);
  11091 
  11092     if (rv != BCM_E_NONE) {
  11093         cli_out("Error in getting FC port config!!\n");
  11094         return CMD_FAIL;
  11095     }
  11096 
  11097     cli_out("    XMOD_FCMAP_ATTR_xxx.                                                     | action_mask                         : %#x\n",    pCfg.action_mask);                      
  11098     cli_out("    XMOD_FCMAP_ATTR2_xxx.                                                    | action_mask2                        : %#x\n",    pCfg.action_mask2);                     
  11099     cli_out("    FC port Mode, FCoE mode                                                  | port_mode                           : %#x\n",    pCfg.port_mode);                        
  11100     cli_out("    Speed, AN/2/4/8/16/32/AN2/AN4/AN8/AN16/AN3                               | speed                               : %#x\n",    pCfg.speed);                            
  11101     cli_out("    Transit B2B credits                                                      | tx_buffer_to_buffer_credits         : %#x\n",    pCfg.tx_buffer_to_buffer_credits);      
  11102     cli_out("    Receive B2B Credits (read only), computed based on max_frame_length      | rx_buffer_to_buffer_credits         : %#x\n",    pCfg.rx_buffer_to_buffer_credits);      
  11103     cli_out("    maximum FC frame length for ingress and egress (in unit of 32-bit word)  | max_frame_length                    : %#x\n",    pCfg.max_frame_length);                 
  11104     cli_out("    bb credit recovery parameter                                             | bb_sc_n                             : %#x\n",    pCfg.bb_sc_n);                          
  11105     cli_out("    Port state, INIT, Reset, Link Up, Link down, disabled (read only)        | port_state                          : %#x\n",    pCfg.port_state);
  11106     cli_out("    Receive, transmit Timeout, default 100ms                                 | r_t_tov                             : %#x\n",    pCfg.r_t_tov);                          
  11107     cli_out("    Interrupt enable                                                         | interrupt_enable                    : %#x\n",    pCfg.interrupt_enable);                 
  11108     cli_out("    fillword on 8G active state                                              | fw_on_active_8g                     : %#x\n",    pCfg.fw_on_active_8g);                  
  11109     cli_out("    Encap Source MAC construct mode                                          | src_mac_construct                   : %#x\n",    pCfg.src_mac_construct);                
  11110     cli_out("    Src MAC Addr for encapsulated frame                                      | src_mac_addr                        : %02x:%02x:%02x:%02x:%02x:%02x\n",
  11111                                                                                                                                 pCfg.src_mac_addr[0], pCfg.src_mac_addr[1], pCfg.src_mac_addr[2],
  11112                                                                                                                                 pCfg.src_mac_addr[3], pCfg.src_mac_addr[4], pCfg.src_mac_addr[5]);
  11113     cli_out("    Source FCMAP prefix for the FPMA                                         | src_fcmap_prefix                    : %#x\n",    pCfg.src_fcmap_prefix);                 
  11114     cli_out("    Encap Dest MAC construct mode                                            | dst_mac_construct                   : %#x\n",    pCfg.dst_mac_construct);                
  11115     cli_out("    Dest MAC Addr for encapsulated frame                                     | dst_mac_addr                        : %02x:%02x:%02x:%02x:%02x:%02x\n",                                                
  11116                                                                                                                                 pCfg.dst_mac_addr[0], pCfg.dst_mac_addr[1], pCfg.dst_mac_addr[2],  
  11117                                                                                                                                 pCfg.dst_mac_addr[3], pCfg.dst_mac_addr[4], pCfg.dst_mac_addr[5]); 
  11118     cli_out("    Destination FCMAP prefix for the FPMA                                    | dst_fcmap_prefix                    : %#x\n",    pCfg.dst_fcmap_prefix);                 
  11119     cli_out("    default vlan for the mapper                                              | vlan_tag                            : %#x\n",    pCfg.vlan_tag);                         
  11120     cli_out("    default VFT tag for the mapper                                           | vft_tag                             : %#x\n",    pCfg.vft_tag);                          
  11121     cli_out("    Size of VLAN-VSAN Mapper table (read only)                               | mapper_len                          : %#x\n",    pCfg.mapper_len);                       
  11122     cli_out("    Bypass Mapper                                                            | ingress_mapper_bypass               : %#x\n",    pCfg.ingress_mapper_bypass);            
  11123     cli_out("    Bypass Mapper                                                            | egress_mapper_bypass                : %#x\n",    pCfg.egress_mapper_bypass);             
  11124     cli_out("    VID or VFID                                                              | ingress_map_table_input             : %#x\n",    pCfg.ingress_map_table_input);          
  11125     cli_out("    VID or VFID                                                              | egress_map_table_input              : %#x\n",    pCfg.egress_map_table_input);           
  11126     cli_out("    Mapper FC-CRC handling                                                   | ingress_fc_crc_mode                 : %#x\n",    pCfg.ingress_fc_crc_mode);              
  11127     cli_out("    Mapper FC-CRC handling                                                   | egress_fc_crc_mode                  : %#x\n",    pCfg.egress_fc_crc_mode);               
  11128     cli_out("    VFT header processing mode                                               | ingress_vfthdr_proc_mode            : %#x\n",    pCfg.ingress_vfthdr_proc_mode);         
  11129     cli_out("    VFT header processing mode                                               | egress_vfthdr_proc_mode             : %#x\n",    pCfg.egress_vfthdr_proc_mode);          
  11130     cli_out("    VLAN header processing mode                                              | ingress_vlantag_proc_mode           : %#x\n",    pCfg.ingress_vlantag_proc_mode);        
  11131     cli_out("    VLAN header processing mode                                              | egress_vlantag_proc_mode            : %#x\n",    pCfg.egress_vlantag_proc_mode);         
  11132     cli_out("    source of VFID                                                           | ingress_vfid_mapsrc                 : %#x\n",    pCfg.ingress_vfid_mapsrc);              
  11133     cli_out("    source of VFID                                                           | egress_vfid_mapsrc                  : %#x\n",    pCfg.egress_vfid_mapsrc);               
  11134     cli_out("    source of VID                                                            | ingress_vid_mapsrc                  : %#x\n",    pCfg.ingress_vid_mapsrc);               
  11135     cli_out("    processing mode for priority field of vlan tag                           | ingress_vlan_pri_map_mode           : %#x\n",    pCfg.ingress_vlan_pri_map_mode);        
  11136     cli_out("    processing mode for priority field of vlan tag                           | egress_vlan_pri_map_mode            : %#x\n",    pCfg.egress_vlan_pri_map_mode);         
  11137     cli_out("    mode of VFT hopCnt check on ingress                                      | ingress_hopCnt_check_mode           : %#x\n",    pCfg.ingress_hopCnt_check_mode);        
  11138     cli_out("    enable VFT hopCnt decrement on egress                                    | egress_hopCnt_dec_enable            : %#x\n",    pCfg.egress_hopCnt_dec_enable);         
  11139     cli_out("    during 16G speed negotiation, 0 -- Use TTS, 1 -- Use PCS                 | use_tts_pcs_16G                     : %#x\n",    pCfg.use_tts_pcs_16G);                  
  11140     cli_out("    during 32G speed negotiation, 0 -- Use TTS, 1 -- Use PCS                 | use_tts_pcs_32G                     : %#x\n",    pCfg.use_tts_pcs_32G);                  
  11141     cli_out("    enable/disable link training for 16G                                     | training_enable_16G                 : %#x\n",    pCfg.training_enable_16G);              
  11142     cli_out("    enable/disable link training for 32G                                     | training_enable_32G                 : %#x\n",    pCfg.training_enable_32G);              
  11143     cli_out("    enable/disable FEC for 16G                                               | fec_enable_16G                      : %#x\n",    pCfg.fec_enable_16G);                   
  11144     cli_out("    enable/disable FEC for 32G                                               | fec_enable_32G                      : %#x\n",    pCfg.fec_enable_32G);                   
  11145     cli_out("    Enable FCS corruption on if FCoE pkt has EOFni or EOFa on ingress        | ingress_fcs_crrpt_eof_enable        : %#x\n",    pCfg.ingress_fcs_crrpt_eof_enable);     
  11146     cli_out("    VLAN header insert enable                                                | ingress_vlantag_presence_enable     : %#x\n",    pCfg.ingress_vlantag_presence_enable);  
  11147     cli_out("    mode of VFT hopCnt check on egress                                       | egress_hopcnt_check_mode            : %#x\n",    pCfg.egress_hopcnt_check_mode);         
  11148     cli_out("    enable VFT hopCnt decrement on ingress                                   | ingress_hopcnt_dec_enable           : %#x\n",    pCfg.ingress_hopcnt_dec_enable);        
  11149     cli_out("    enable passing control frame on egress when mapper is in bypass mode     | egress_pass_ctrl_frame_enable       : %#x\n",    pCfg.egress_pass_ctrl_frame_enable);    
  11150     cli_out("    enable passing pfc frame on egress when mapper is in bypass mode         | egress_pass_pfc_frame_enable        : %#x\n",    pCfg.egress_pass_pfc_frame_enable);     
  11151     cli_out("    enable passing pause frame on egress when mapper is in bypass mode       | egress_pass_pause_frame_enable      : %#x\n",    pCfg.egress_pass_pause_frame_enable);   
  11152     cli_out("    disable FCOE header version field check on egress                        | egress_fcoe_version_chk_disable     : %#x\n",    pCfg.egress_fcoe_version_chk_disable);  
  11153     cli_out("    specify default CoS value to use on egress                               | egress_default_cos_value            : %#x\n",    pCfg.egress_default_cos_value);         
  11154     cli_out("    use IP CoS map values on egress                                          | egress_use_ip_cos_map               : %#x\n",    pCfg.egress_use_ip_cos_map);            
  11155     cli_out("    bitmap to enable/disable scrambling for 2/4/8/16/32G FC speed            | scrambling_enable_mask              : %#x\n",    pCfg.scrambling_enable_mask);           
  11156     cli_out("    0 - disable, 1 - enable: bitmap value for corresponding speed            | scrambling_enable_value             : %#x\n",    pCfg.scrambling_enable_value);          
  11157     cli_out("    0 - disable, 1 - enable); legacy pause on egress                         | egress_pause_enable                 : %#x\n",    pCfg.egress_pause_enable);              
  11158     cli_out("    0 - disable, 1 - enable); PFC on egress                                  | egress_pfc_enable                   : %#x\n",    pCfg.egress_pfc_enable);                
  11159     cli_out("    stats collection interval in milliseconds                                | stat_interval                       : %#x\n",    pCfg.stat_interval);                    
  11160     cli_out("    current COS value                                                        | cos_to_pri.cos                      : %#x\n",    pCfg.cos_to_pri.cos);
  11161     cli_out("    current priority value                                                   | cos_to_pri.pri                      : %#x\n",    pCfg.cos_to_pri.pri);
  11162 
  11163     return CMD_OK;
  11164 }
  11165 
  11166 #endif