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

portmod_chain.c (187125B)


      1 
      2 /*
      3  *         
      4  * 
      5  * 
      6  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      7  * 
      8  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      9  */
     10  
     11 #include <shared/bsl.h>
     12 #include <soc/drv.h>
     13 #include <soc/types.h>
     14 #include <soc/error.h>
     15 #include <soc/phyreg.h>
     16 #include <soc/wb_engine.h>
     17 #include <soc/portmod/portmod_internal.h>
     18 #include <soc/portmod/portmod.h>
     19 #include <soc/portmod/portmod_common.h>
     20 #include <soc/portmod/portmod_dispatch.h>
     21 #include <soc/portmod/portmod_legacy_phy.h>
     22 #include <soc/portmod/portmod_chain.h>
     23 
     24 #ifdef _ERR_MSG_MODULE_NAME 
     25 #error "_ERR_MSG_MODULE_NAME redefined" 
     26 #endif
     27 #define _ERR_MSG_MODULE_NAME BSL_LS_SOC_PORT
     28 
     29 #define PM_EXTPHY_ITER(rv, phy_idx)    while((PHYMOD_E_UNAVAIL== rv) && (phy_idx >= 0))
     30 #define PM_ALLPHY_ITER(rv, phy_idx)    while(((rv == PHYMOD_E_NONE) || (rv == PHYMOD_E_UNAVAIL)) && (phy_idx >= 0))
     31 
     32 typedef enum xphy_wb_vars {
     33     xphy_wb_is_initialized,                 /* keep track of xphy initialization state.     */
     34     xphy_wb_phy_type,                       /* xphy probed phy type information.            */
     35     xphy_wb_legacy_phy_present,             /* indicates if port has legacy external phy    */
     36     xphy_wb_ref_clk,                        /* xphy ref clk                                 */
     37     xphy_wb_fw_load_method,                 /* xphy firmware load method.                   */
     38     xphy_wb_force_fw_load,                  /* xphy force firmware load indication.         */
     39     xphy_wb_polarity,                       /* xphy polarity information.                   */
     40     xphy_wb_lane_map,                       /* xphy lane map information.                   */
     41     xphy_wb_device_op_mode,                 /* xphy device_op_mode of core_access.          */
     42     xphy_wb_primary_core_num,               /* xphy primary core information.               */
     43     xphy_wb_core_probed,                    /* indicate xphy core has been probed or not    */
     44     xphy_wb_active_lanes,                   /* indicate xphy lanes that are connected/used. */
     45     xphy_wb_num_var
     46 }xphy_wb_vars_t;
     47 
     48 typedef struct portmod_xphy_info_s {
     49     phymod_core_access_t core_access; /**< core access */
     50     int wb_var_ids[xphy_wb_num_var];
     51 } portmod_xphy_info_t;
     52 
     53 #define XPHY_WB_BUFFER_VERSION      (4)
     54 #define XPHY_IS_INITIALIZED_SET(unit, xphy_info, is_initialized)  \
     55     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_is_initialized], &is_initialized);
     56 #define XPHY_IS_INITIALIZED_GET(unit, xphy_info, is_initialized)  \
     57     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_is_initialized], is_initialized);
     58 
     59 #define XPHY_PHY_TYPE_SET(unit, xphy_info, phy_type)  \
     60     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_phy_type], &phy_type);
     61 #define XPHY_PHY_TYPE_GET(unit, xphy_info, phy_type)  \
     62     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_phy_type], phy_type);
     63 
     64 #define XPHY_LEGACY_PHY_PRESENT_SET(unit, xphy_info, leagacy_phy_present)  \
     65     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_legacy_phy_present], &leagacy_phy_present);
     66 #define XPHY_LEGACY_PHY_PRESENT_GET(unit, xphy_info, leagacy_phy_present)  \
     67     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_legacy_phy_present], leagacy_phy_present);
     68 
     69 #define XPHY_REF_CLK_SET(unit, xphy_info, ref_clk)  \
     70     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_ref_clk], &ref_clk);
     71 #define XPHY_REF_CLK_GET(unit, xphy_info, ref_clk)  \
     72     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_ref_clk], ref_clk );
     73 
     74 #define XPHY_FW_LOAD_METHOD_SET(unit, xphy_info, fw_load_method)  \
     75     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_fw_load_method], &fw_load_method);
     76 #define XPHY_FW_LOAD_METHOD_GET(unit, xphy_info, fw_load_method)  \
     77     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_fw_load_method], fw_load_method);
     78 
     79 #define XPHY_FORCE_FW_LOAD_SET(unit, xphy_info, force_fw_load)  \
     80     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_force_fw_load], &force_fw_load);
     81 #define XPHY_FORCE_FW_LOAD_GET(unit, xphy_info, force_fw_load)  \
     82     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_force_fw_load], force_fw_load);
     83 
     84 #define XPHY_POLARITY_SET(unit, xphy_info, polarity)  \
     85     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_polarity], &polarity);
     86 #define XPHY_POLARITY_GET(unit, xphy_info, polarity)  \
     87     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_polarity], polarity);
     88 
     89 #define XPHY_LANE_MAP_SET(unit, xphy_info, lane_map)  \
     90     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_lane_map], &lane_map);
     91 #define XPHY_LANE_MAP_GET(unit, xphy_info, lane_map)  \
     92     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_lane_map], lane_map );
     93 
     94 #define XPHY_DEVICE_OP_MODE_SET(unit, xphy_info, device_op_mode)  \
     95     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_device_op_mode], &device_op_mode);
     96 #define XPHY_DEVICE_OP_MODE_GET(unit, xphy_info, device_op_mode)  \
     97     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_device_op_mode], device_op_mode);
     98 
     99 #define XPHY_PRIMARY_CORE_NUM_SET(unit, xphy_info, primary_core_num )  \
    100     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_primary_core_num], &primary_core_num);
    101 #define XPHY_PRIMARY_CORE_NUM_GET(unit, xphy_info, primary_core_num)  \
    102     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_primary_core_num], primary_core_num);
    103 
    104 #define XPHY_CORE_PROBED_SET(unit, xphy_info, core_probed)  \
    105     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_core_probed], &core_probed);
    106 #define XPHY_CORE_PROBED_GET(unit, xphy_info, core_probed)  \
    107     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_core_probed], core_probed);
    108 
    109 #define XPHY_ACTIVE_LANES_SET(unit, xphy_info, active_lanes)  \
    110     SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_active_lanes], &active_lanes);
    111 #define XPHY_ACTIVE_LANES_GET(unit, xphy_info, active_lanes)  \
    112     SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, xphy_info->wb_var_ids[xphy_wb_active_lanes], active_lanes);
    113 
    114 portmod_ext_phy_core_info_t *_ext_phy_info[SOC_MAX_NUM_DEVICES][MAX_PHYN][SOC_MAX_NUM_PORTS] = {{{NULL}}};
    115 
    116 STATIC
    117 portmod_xphy_info_t* _xphy_info[SOC_MAX_NUM_DEVICES][PORTMOD_MAX_NUM_XPHY_SUPPORTED];
    118 
    119 STATIC void* _xphy_user_access[SOC_MAX_NUM_DEVICES * PORTMOD_MAX_NUM_XPHY_SUPPORTED] = {NULL};
    120 
    121 STATIC
    122 phymod_core_init_config_t _xphy_core_config[SOC_MAX_NUM_DEVICES][PORTMOD_MAX_NUM_XPHY_SUPPORTED];
    123 
    124 STATIC
    125 int _xphy_addr[SOC_MAX_NUM_DEVICES][PORTMOD_MAX_NUM_XPHY_SUPPORTED];
    126 
    127 int portmod_xphy_addr_set(int unit, int idx, int xphy_addr)
    128 {
    129     _xphy_addr[unit][idx] = xphy_addr;
    130     return SOC_E_NONE;
    131 }
    132 
    133 int portmod_phychain_ext_phy_info_set(int unit, int phyn, int core_index, const portmod_ext_phy_core_info_t* core_info)
    134 {
    135     SOC_INIT_FUNC_DEFS;
    136 
    137     if (((1 + MAX_PHYN) <= phyn) || (0 >= phyn)){
    138         _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("phyn is out of the range of allowed external phys")));
    139     }
    140     if(NULL == _ext_phy_info[unit][phyn - 1][core_index]){
    141         _ext_phy_info[unit][phyn - 1][core_index] = sal_alloc(sizeof(portmod_ext_phy_core_info_t), "core_info");
    142         if(NULL == _ext_phy_info[unit][phyn - 1][core_index]){
    143             _SOC_EXIT_WITH_ERR(SOC_E_MEMORY, (_SOC_MSG("phyn core info mem allocation failed")));
    144         }
    145     }
    146     sal_memcpy(_ext_phy_info[unit][phyn - 1][core_index], core_info, sizeof(portmod_ext_phy_core_info_t));
    147 
    148 exit:
    149     SOC_FUNC_RETURN; 
    150 }
    151 
    152 int portmod_phychain_ext_phy_info_get(int unit, int phyn, int core_index, portmod_ext_phy_core_info_t* core_info)
    153 {
    154     SOC_INIT_FUNC_DEFS;
    155 
    156     if (((1 + MAX_PHYN) <= phyn) || (0 >= phyn)){
    157         _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("phyn is out of the range of allowed external phys")));
    158     }
    159     if(NULL == _ext_phy_info[unit][phyn - 1][core_index]){
    160         _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, (_SOC_MSG("for phyn core,the information is not available")));
    161     }
    162     sal_memcpy(core_info, _ext_phy_info[unit][phyn - 1][core_index], sizeof(portmod_ext_phy_core_info_t));
    163 
    164 exit:
    165     SOC_FUNC_RETURN; 
    166 }
    167 
    168 int portmod_ext_phy_core_info_t_init(int unit, portmod_ext_phy_core_info_t* portmod_ext_phy_core_info)
    169 {
    170     SOC_INIT_FUNC_DEFS;
    171 
    172     if(portmod_ext_phy_core_info == NULL){
    173         _SOC_EXIT_WITH_ERR(SOC_E_PARAM, ("portmod_ext_phy_core_info NULL parameter"));
    174     }
    175     sal_memset(portmod_ext_phy_core_info, 0, sizeof(portmod_ext_phy_core_info_t));
    176     phymod_core_access_t_init(&portmod_ext_phy_core_info->core_access);
    177     portmod_ext_phy_core_info->is_initialized = 0;
    178 
    179 exit:
    180     SOC_FUNC_RETURN;
    181 }
    182 
    183 int portmod_xphy_wb_buffer_init(int unit, uint32 wb_buffer_index, portmod_xphy_info_t* xphy_core_info)
    184 {
    185     /* Declare the common variables needed for warmboot */
    186     WB_ENGINE_INIT_TABLES_DEFS;
    187     int wb_var_id, rv = 0;
    188     int buffer_id = wb_buffer_index; /*required by SOC_WB_ENGINE_ADD_ Macros*/
    189     SOC_INIT_FUNC_DEFS;
    190 
    191     COMPILER_REFERENCE(buffer_is_dynamic);
    192     SOC_WB_ENGINE_ADD_BUFF(SOC_WB_ENGINE_PORTMOD, wb_buffer_index, "xphy", NULL, NULL, XPHY_WB_BUFFER_VERSION, 1, SOC_WB_ENGINE_PRE_RELEASE);
    193     _SOC_IF_ERR_EXIT(rv);
    194 
    195     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
    196     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_initialized", wb_buffer_index, sizeof(uint32), NULL, VERSION(1));
    197     _SOC_IF_ERR_EXIT(rv);
    198     xphy_core_info->wb_var_ids[xphy_wb_is_initialized ]= wb_var_id;
    199 
    200     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
    201     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "phy_type", wb_buffer_index, sizeof(uint32), NULL, VERSION(1));
    202     _SOC_IF_ERR_EXIT(rv);
    203     xphy_core_info->wb_var_ids[xphy_wb_phy_type]= wb_var_id;
    204 
    205     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
    206     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "is_legacy_ext_phy", wb_buffer_index, sizeof(uint32), NULL, VERSION(2));
    207     _SOC_IF_ERR_EXIT(rv);
    208     xphy_core_info->wb_var_ids[xphy_wb_legacy_phy_present]= wb_var_id;
    209 
    210     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
    211     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "xphy_wb_ref_clk", wb_buffer_index, sizeof(phymod_ref_clk_t), NULL, VERSION(3));
    212     _SOC_IF_ERR_EXIT(rv);
    213     xphy_core_info->wb_var_ids[xphy_wb_ref_clk]= wb_var_id;
    214 
    215     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
    216     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "xphy_wb_fw_load_method", wb_buffer_index, sizeof(phymod_firmware_load_method_t ), NULL, VERSION(3));
    217     _SOC_IF_ERR_EXIT(rv);
    218     xphy_core_info->wb_var_ids[xphy_wb_fw_load_method]= wb_var_id;
    219 
    220     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
    221     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "xphy_wb_force_fw_load", wb_buffer_index, sizeof(int), NULL, VERSION(3));
    222     _SOC_IF_ERR_EXIT(rv);
    223     xphy_core_info->wb_var_ids[xphy_wb_force_fw_load]= wb_var_id;
    224 
    225     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
    226     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "xphy_wb_polarity", wb_buffer_index, sizeof(phymod_polarity_t ), NULL, VERSION(3));
    227     _SOC_IF_ERR_EXIT(rv);
    228     xphy_core_info->wb_var_ids[xphy_wb_polarity]= wb_var_id;
    229 
    230     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
    231     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "xphy_wb_lane_map", wb_buffer_index, sizeof(phymod_lane_map_t), NULL, VERSION(3));
    232     _SOC_IF_ERR_EXIT(rv);
    233     xphy_core_info->wb_var_ids[xphy_wb_lane_map]= wb_var_id;
    234 
    235     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
    236     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "xphy_wb_device_op_mode", wb_buffer_index, sizeof(uint32), NULL, VERSION(3));
    237     _SOC_IF_ERR_EXIT(rv);
    238     xphy_core_info->wb_var_ids[xphy_wb_device_op_mode]= wb_var_id;
    239 
    240 
    241     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
    242     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "xphy_wb_primary_core_num", wb_buffer_index, sizeof(uint32), NULL, VERSION(3));
    243     _SOC_IF_ERR_EXIT(rv);
    244     xphy_core_info->wb_var_ids[xphy_wb_primary_core_num]= wb_var_id;
    245 
    246     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
    247     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "xphy_wb_core_probed", wb_buffer_index, sizeof(int), NULL, VERSION(3));
    248     xphy_core_info->wb_var_ids[xphy_wb_core_probed]= wb_var_id;
    249     _SOC_IF_ERR_EXIT(rv);
    250 
    251     _SOC_IF_ERR_EXIT(portmod_next_wb_var_id_get(unit, &wb_var_id));
    252     SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, wb_var_id, "xphy_wb_active_lanes", wb_buffer_index, sizeof(uint32), NULL, VERSION(4));
    253     xphy_core_info->wb_var_ids[xphy_wb_active_lanes]= wb_var_id;
    254     _SOC_IF_ERR_EXIT(rv);
    255 
    256     _SOC_IF_ERR_EXIT(soc_wb_engine_init_buffer(unit, SOC_WB_ENGINE_PORTMOD, wb_buffer_index, FALSE));
    257 
    258 exit:
    259     SOC_FUNC_RETURN;
    260 }
    261 
    262 STATIC
    263 int _xphy_find_index(int unit, int xphy_addr, int* xphy_id)
    264 {
    265     int idx;
    266 
    267     *xphy_id = PORTMOD_MAX_NUM_XPHY_SUPPORTED;
    268     for (idx=0; idx<PORTMOD_MAX_NUM_XPHY_SUPPORTED; idx++) {
    269         if (_xphy_info[unit][idx] != NULL) {
    270             if (_xphy_info[unit][idx]->core_access.access.addr == xphy_addr) {
    271                 *xphy_id = idx;
    272                 return SOC_E_NONE;
    273             }
    274         } else {
    275             if (*xphy_id == PORTMOD_MAX_NUM_XPHY_SUPPORTED)
    276                 *xphy_id = idx;
    277         }
    278     }
    279 
    280     return SOC_E_PARAM;
    281 }
    282 
    283 int portmod_chain_xphy_add_by_index(int unit, int xphy_idx, int xphy_addr, const phymod_core_access_t* core_access)
    284 {
    285     int rv;
    286     int max_pms=0;
    287     uint32 wb_buffer_index;
    288     phymod_dispatch_type_t phy_type;
    289     phymod_ref_clk_t ref_clk; 
    290     phymod_firmware_load_method_t fw_load_method;
    291     int is_initialized;
    292     int core_probed; 
    293     uint32 active_lanes;
    294  
    295     SOC_INIT_FUNC_DEFS;
    296 
    297     /* if new one need to be added, create one.  */
    298     if( NULL == _xphy_info[unit][xphy_idx]){
    299 
    300         _xphy_info[unit][xphy_idx] = sal_alloc(sizeof(portmod_xphy_info_t), "xphy_info");
    301 
    302         if(NULL == _xphy_info[unit][xphy_idx]){
    303             _SOC_EXIT_WITH_ERR(SOC_E_MEMORY, (_SOC_MSG("xphy core info mem allocation failed")));
    304         }
    305         /* start with clean memory. */
    306         sal_memset(_xphy_info[unit][xphy_idx], 0, sizeof(portmod_xphy_info_t));
    307 
    308     } else {
    309         /* existing one, does not need any action. */
    310         SOC_EXIT;
    311     }
    312 
    313     sal_memcpy(&_xphy_info[unit][xphy_idx]->core_access, core_access, sizeof(phymod_core_access_t));
    314     _xphy_info[unit][xphy_idx]->core_access.access.addr = xphy_addr;
    315 
    316     /* initialize the warmboot variables */
    317     portmod_max_pms_get(unit, &max_pms);
    318     wb_buffer_index = xphy_idx + max_pms + 1;
    319     _SOC_IF_ERR_EXIT(portmod_xphy_wb_buffer_init(unit, wb_buffer_index, _xphy_info[unit][xphy_idx]));
    320 
    321     /* if warmboot, restore the probed phy type into the phymod core_access. */
    322     if(SOC_WARM_BOOT(unit)){
    323 
    324         rv = XPHY_PHY_TYPE_GET(unit,_xphy_info[unit][xphy_idx],
    325                             &_xphy_info[unit][xphy_idx]->core_access.type);
    326         _SOC_IF_ERR_EXIT(rv);
    327 
    328         rv = XPHY_DEVICE_OP_MODE_GET(unit,_xphy_info[unit][xphy_idx],
    329                             &_xphy_info[unit][xphy_idx]->core_access.device_op_mode);
    330         _SOC_IF_ERR_EXIT(rv);
    331 
    332     }
    333 
    334     if(!SOC_WARM_BOOT(unit)){
    335         portmod_xphy_db_addr_set(unit, xphy_idx, xphy_addr);
    336 
    337         phy_type = phymodDispatchTypeInvalid;
    338         rv = XPHY_PHY_TYPE_SET(unit,_xphy_info[unit][xphy_idx], phy_type);
    339         _SOC_IF_ERR_EXIT(rv);
    340 
    341         is_initialized =0;
    342         rv = XPHY_IS_INITIALIZED_SET(unit,_xphy_info[unit][xphy_idx],is_initialized);
    343         _SOC_IF_ERR_EXIT(rv);
    344 
    345         ref_clk = phymodRefClkCount;
    346         rv = XPHY_REF_CLK_SET(unit,_xphy_info[unit][xphy_idx],ref_clk);
    347         _SOC_IF_ERR_EXIT(rv);
    348 
    349         fw_load_method = phymodFirmwareLoadMethodCount;
    350         rv = XPHY_FW_LOAD_METHOD_SET(unit,_xphy_info[unit][xphy_idx],fw_load_method);
    351         _SOC_IF_ERR_EXIT(rv);
    352 
    353         core_probed =  0;
    354         rv = XPHY_CORE_PROBED_SET(unit,_xphy_info[unit][xphy_idx],core_probed);
    355         _SOC_IF_ERR_EXIT(rv);
    356 
    357         /*
    358          * clear all the active lanes.
    359          */
    360         active_lanes = 0;
    361         rv = XPHY_ACTIVE_LANES_SET(unit,_xphy_info[unit][xphy_idx],active_lanes);
    362         _SOC_IF_ERR_EXIT(rv);
    363         
    364     }
    365 exit:
    366     SOC_FUNC_RETURN;
    367 }
    368 
    369 int portmod_chain_xphy_add(int unit, int xphy_addr, const phymod_core_access_t* core_access, int *xphy_idx_out)
    370 {
    371     int xphy_idx ;
    372     SOC_INIT_FUNC_DEFS;
    373 
    374     /* looking for the matching valid one, if found, skip and return. */
    375     *xphy_idx_out = PORTMOD_MAX_NUM_XPHY_SUPPORTED;
    376     if (_xphy_find_index(unit,xphy_addr, xphy_idx_out) == SOC_E_NONE){
    377         /*
    378          * if the xphy is already in database, the user_acc need to be 
    379          * release from  caller.
    380          */
    381 
    382         *xphy_idx_out = PORTMOD_XPHY_EXISTING_IDX;
    383         SOC_EXIT;
    384     }
    385     xphy_idx = *xphy_idx_out; 
    386 
    387     if ( PORTMOD_MAX_NUM_XPHY_SUPPORTED <= xphy_idx){
    388         _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("xphy_idx is out of the range of allowed external phys - 0- %d"), (PORTMOD_MAX_NUM_XPHY_SUPPORTED-1)));
    389     }
    390 
    391     _SOC_IF_ERR_EXIT(portmod_chain_xphy_add_by_index(unit, xphy_idx, xphy_addr, core_access));
    392 exit:
    393     SOC_FUNC_RETURN;
    394 }
    395 
    396 int portmod_chain_xphy_user_access_store(int unit, int xphy_idx, void* user_acc)
    397 {
    398     _xphy_user_access[(unit * PORTMOD_MAX_NUM_XPHY_SUPPORTED)+xphy_idx] = user_acc;
    399     return SOC_E_NONE;
    400 }
    401 
    402 
    403 void portmod_chain_xphy_user_access_release(int unit)
    404 {
    405     int idx;
    406     portmod_default_user_access_t *local_user_access;
    407 
    408     for (idx=0; idx<PORTMOD_MAX_NUM_XPHY_SUPPORTED; idx++) {
    409         local_user_access = (portmod_default_user_access_t*)_xphy_user_access[(unit * PORTMOD_MAX_NUM_XPHY_SUPPORTED)+idx];
    410         if(local_user_access != NULL) {
    411             if(local_user_access->mutex != NULL) {
    412                 sal_mutex_destroy(local_user_access->mutex);
    413             }
    414             sal_free(local_user_access);
    415             _xphy_user_access[(unit * PORTMOD_MAX_NUM_XPHY_SUPPORTED)+idx] = NULL;
    416         }
    417     }
    418 }
    419 
    420 int _xphy_resource_release(int unit, int xphy_idx)
    421 {
    422 
    423     portmod_xphy_info_t* xphy_info;
    424     SOC_INIT_FUNC_DEFS;
    425 
    426     xphy_info = _xphy_info[unit][xphy_idx];
    427 
    428     if( xphy_info != NULL ) {
    429         sal_free(_xphy_info[unit][xphy_idx]);
    430         _xphy_info[unit][xphy_idx] = NULL ;
    431         /* How to remove wb data for the xphy? */
    432     }
    433     SOC_FUNC_RETURN;
    434 }
    435 
    436 int portmod_chain_xphy_delete(int unit, int xphy_addr)
    437 {
    438     int xphy_idx;
    439 
    440     SOC_INIT_FUNC_DEFS;
    441     
    442     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    443     _SOC_IF_ERR_EXIT(portmod_xphy_valid_phy_set (unit, xphy_idx, FALSE));
    444 
    445     /* release all resource of xphy_info */
    446     _SOC_IF_ERR_EXIT(_xphy_resource_release(unit, xphy_idx));
    447 
    448 exit:
    449     SOC_FUNC_RETURN;
    450 }
    451 
    452 int portmod_chain_xphy_delete_all(int unit)
    453 {
    454     int xphy_idx;
    455 
    456     SOC_INIT_FUNC_DEFS;
    457 
    458     for(xphy_idx = 0; xphy_idx < PORTMOD_MAX_NUM_XPHY_SUPPORTED; xphy_idx++){
    459         /* release all resource of xphy_info */
    460         _SOC_IF_ERR_EXIT(_xphy_resource_release(unit, xphy_idx));
    461     }
    462 exit:
    463     SOC_FUNC_RETURN;
    464 }
    465 
    466 int portmod_xphy_core_access_set(int unit, uint32 xphy_addr, phymod_core_access_t *core_access, int is_legacy_phy)
    467 {
    468     int xphy_idx, rv;
    469     SOC_INIT_FUNC_DEFS;
    470 
    471     SOC_IF_ERROR_RETURN(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    472 
    473     sal_memcpy( &_xphy_info[unit][xphy_idx]->core_access, core_access,  sizeof(phymod_core_access_t));
    474 
    475     rv = XPHY_PHY_TYPE_SET(unit,_xphy_info[unit][xphy_idx], core_access->type);
    476     _SOC_IF_ERR_EXIT(rv);
    477 
    478     rv = XPHY_LEGACY_PHY_PRESENT_SET(unit,_xphy_info[unit][xphy_idx], is_legacy_phy);
    479     _SOC_IF_ERR_EXIT(rv);
    480 
    481     rv = XPHY_DEVICE_OP_MODE_SET(unit,_xphy_info[unit][xphy_idx], core_access->device_op_mode);
    482     _SOC_IF_ERR_EXIT(rv);
    483 
    484 exit:
    485     SOC_FUNC_RETURN;
    486 }
    487 
    488 int portmod_xphy_core_access_get(int unit, uint32 xphy_addr, phymod_core_access_t *core_access, int* is_legacy_phy)
    489 {
    490     int rv;
    491     int xphy_idx;
    492     SOC_INIT_FUNC_DEFS;
    493 
    494     SOC_IF_ERROR_RETURN(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    495     sal_memcpy( core_access, &_xphy_info[unit][xphy_idx]->core_access, sizeof(phymod_core_access_t));
    496 
    497     rv = XPHY_PHY_TYPE_GET(unit,_xphy_info[unit][xphy_idx], &core_access->type);
    498     _SOC_IF_ERR_EXIT(rv);
    499 
    500     rv = XPHY_LEGACY_PHY_PRESENT_GET(unit,_xphy_info[unit][xphy_idx], is_legacy_phy);
    501     _SOC_IF_ERR_EXIT(rv);
    502 
    503     rv = XPHY_DEVICE_OP_MODE_GET(unit,_xphy_info[unit][xphy_idx], &core_access->device_op_mode);
    504     _SOC_IF_ERR_EXIT(rv);
    505 exit:
    506     SOC_FUNC_RETURN;
    507 }
    508 
    509 int portmod_xphy_core_config_set(int unit, uint32 xphy_addr, phymod_core_init_config_t* core_config)
    510 {
    511     int xphy_idx ;
    512     SOC_INIT_FUNC_DEFS;
    513 
    514     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    515     sal_memcpy( &_xphy_core_config[unit][xphy_idx], core_config,  sizeof(phymod_core_init_config_t));
    516 
    517 exit:
    518     SOC_FUNC_RETURN;
    519 }
    520 
    521 int portmod_xphy_core_config_get(int unit, uint32 xphy_addr,phymod_core_init_config_t* core_config)
    522 {
    523     int xphy_idx ;
    524     SOC_INIT_FUNC_DEFS;
    525 
    526     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    527     sal_memcpy( core_config, &_xphy_core_config[unit][xphy_idx], sizeof(phymod_core_init_config_t));
    528 
    529 exit:
    530     SOC_FUNC_RETURN;
    531 }
    532 
    533 
    534 int portmod_xphy_is_initialized_set(int unit, uint32 xphy_addr, int is_initialized)
    535 {
    536     int xphy_idx, rv;
    537     SOC_INIT_FUNC_DEFS;
    538 
    539     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    540     rv = XPHY_IS_INITIALIZED_SET(unit,_xphy_info[unit][xphy_idx], is_initialized);
    541     _SOC_IF_ERR_EXIT(rv);
    542 
    543 exit:
    544     SOC_FUNC_RETURN;
    545 }
    546 
    547 int portmod_xphy_is_initialized_get(int unit, uint32 xphy_addr, int* is_initialized)
    548 {
    549     int xphy_idx, rv;
    550     SOC_INIT_FUNC_DEFS;
    551 
    552     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    553     rv = XPHY_IS_INITIALIZED_GET(unit,_xphy_info[unit][xphy_idx], is_initialized);
    554     _SOC_IF_ERR_EXIT(rv);
    555 
    556 exit:
    557     SOC_FUNC_RETURN;
    558 }
    559 
    560 int portmod_xphy_phy_type_set(int unit, uint32 xphy_addr, phymod_dispatch_type_t phy_type)
    561 {
    562     int xphy_idx, rv;
    563     SOC_INIT_FUNC_DEFS;
    564 
    565     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    566     rv = XPHY_PHY_TYPE_SET(unit,_xphy_info[unit][xphy_idx], phy_type);
    567     _SOC_IF_ERR_EXIT(rv);
    568 
    569 exit:
    570     SOC_FUNC_RETURN;
    571 }
    572 
    573 int portmod_xphy_phy_type_get(int unit, uint32 xphy_addr, phymod_dispatch_type_t* phy_type)
    574 {
    575     int xphy_idx, rv;
    576     SOC_INIT_FUNC_DEFS;
    577 
    578     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    579     rv = XPHY_PHY_TYPE_GET(unit,_xphy_info[unit][xphy_idx], phy_type);
    580     _SOC_IF_ERR_EXIT(rv);
    581 
    582 exit:
    583     SOC_FUNC_RETURN;
    584 }
    585 
    586 int portmod_xphy_is_legacy_phy_set(int unit, uint32 xphy_addr, int is_legacy_phy)
    587 {
    588     int xphy_idx, rv;
    589     SOC_INIT_FUNC_DEFS;
    590 
    591     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    592     rv = XPHY_LEGACY_PHY_PRESENT_SET(unit,_xphy_info[unit][xphy_idx], is_legacy_phy);
    593     _SOC_IF_ERR_EXIT(rv);
    594 
    595 exit:
    596     SOC_FUNC_RETURN;
    597 }
    598 
    599 int portmod_xphy_is_legacy_phy_get(int unit, uint32 xphy_addr, int* is_legacy_phy)
    600 {
    601     int xphy_idx, rv;
    602     SOC_INIT_FUNC_DEFS;
    603 
    604     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    605     rv = XPHY_LEGACY_PHY_PRESENT_GET(unit,_xphy_info[unit][xphy_idx], is_legacy_phy);
    606     _SOC_IF_ERR_EXIT(rv);
    607 
    608 exit:
    609     SOC_FUNC_RETURN;
    610 }
    611 
    612 int portmod_xphy_ref_clk_set(int unit, uint32 xphy_addr, phymod_ref_clk_t ref_clk)
    613 {
    614     int xphy_idx, rv;
    615     SOC_INIT_FUNC_DEFS;
    616 
    617     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    618     rv = XPHY_REF_CLK_SET(unit,_xphy_info[unit][xphy_idx],ref_clk);
    619     _SOC_IF_ERR_EXIT(rv);
    620 
    621 exit:
    622     SOC_FUNC_RETURN;
    623 }
    624 
    625 int portmod_xphy_ref_clk_get(int unit, uint32 xphy_addr, phymod_ref_clk_t* ref_clk)
    626 {
    627     int xphy_idx, rv;
    628     SOC_INIT_FUNC_DEFS;
    629 
    630     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    631     rv = XPHY_REF_CLK_GET(unit,_xphy_info[unit][xphy_idx],ref_clk);
    632     _SOC_IF_ERR_EXIT(rv);
    633 
    634 exit:
    635     SOC_FUNC_RETURN;
    636 }
    637 
    638 int portmod_xphy_fw_load_method_set(int unit, uint32 xphy_addr, phymod_firmware_load_method_t  fw_load_method)
    639 {
    640     int xphy_idx, rv;
    641     SOC_INIT_FUNC_DEFS;
    642 
    643     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    644     rv = XPHY_FW_LOAD_METHOD_SET(unit,_xphy_info[unit][xphy_idx], fw_load_method);
    645     _SOC_IF_ERR_EXIT(rv);
    646 
    647 exit:
    648     SOC_FUNC_RETURN;
    649 }
    650 
    651 int portmod_xphy_fw_load_method_get(int unit, uint32 xphy_addr, phymod_firmware_load_method_t* fw_load_method)
    652 {
    653     int xphy_idx, rv;
    654     SOC_INIT_FUNC_DEFS;
    655 
    656     SOC_IF_ERROR_RETURN(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    657     rv = XPHY_FW_LOAD_METHOD_GET(unit,_xphy_info[unit][xphy_idx], fw_load_method);
    658     _SOC_IF_ERR_EXIT(rv);
    659 
    660 exit:
    661     SOC_FUNC_RETURN;
    662 }
    663 
    664 int portmod_xphy_force_fw_load_set(int unit, uint32 xphy_addr, int force_fw_load)
    665 {
    666     int xphy_idx, rv;
    667     SOC_INIT_FUNC_DEFS;
    668 
    669     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    670     rv = XPHY_FORCE_FW_LOAD_SET(unit,_xphy_info[unit][xphy_idx], force_fw_load);
    671     _SOC_IF_ERR_EXIT(rv);
    672 
    673 exit:
    674     SOC_FUNC_RETURN;
    675 }
    676 
    677 int portmod_xphy_force_fw_load_get(int unit, uint32 xphy_addr, int* force_fw_load)
    678 {
    679     int xphy_idx, rv;
    680     SOC_INIT_FUNC_DEFS;
    681 
    682     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    683     rv = XPHY_FORCE_FW_LOAD_GET(unit,_xphy_info[unit][xphy_idx], force_fw_load);
    684     _SOC_IF_ERR_EXIT(rv);
    685 
    686 exit:
    687     SOC_FUNC_RETURN;
    688 }
    689 
    690 int portmod_xphy_polarity_set(int unit, uint32 xphy_addr, phymod_polarity_t polarity)
    691 {
    692     int xphy_idx, rv;
    693     SOC_INIT_FUNC_DEFS;
    694 
    695     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    696     rv = XPHY_POLARITY_SET(unit,_xphy_info[unit][xphy_idx], polarity);
    697     _SOC_IF_ERR_EXIT(rv);
    698 
    699 exit:
    700     SOC_FUNC_RETURN;
    701 }
    702 
    703 int portmod_xphy_polarity_get(int unit, uint32 xphy_addr, phymod_polarity_t* polarity)
    704 {
    705     int xphy_idx, rv;
    706     SOC_INIT_FUNC_DEFS;
    707 
    708     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    709     rv = XPHY_POLARITY_GET(unit,_xphy_info[unit][xphy_idx], polarity);
    710     _SOC_IF_ERR_EXIT(rv);
    711 
    712 exit:
    713     SOC_FUNC_RETURN;
    714 }
    715 
    716 int portmod_xphy_lane_map_set(int unit, uint32 xphy_addr, phymod_lane_map_t lane_map)
    717 {
    718     int xphy_idx, rv;
    719     SOC_INIT_FUNC_DEFS;
    720 
    721     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    722     rv = XPHY_LANE_MAP_SET(unit,_xphy_info[unit][xphy_idx], lane_map);
    723     _SOC_IF_ERR_EXIT(rv);
    724 
    725 exit:
    726     SOC_FUNC_RETURN;
    727 }
    728 
    729 int portmod_xphy_lane_map_get(int unit, uint32 xphy_addr, phymod_lane_map_t* lane_map)
    730 {
    731     int xphy_idx, rv;
    732     SOC_INIT_FUNC_DEFS;
    733 
    734     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    735     rv = XPHY_LANE_MAP_GET(unit,_xphy_info[unit][xphy_idx], lane_map);
    736     _SOC_IF_ERR_EXIT(rv);
    737 
    738 exit:
    739     SOC_FUNC_RETURN;
    740 }
    741 
    742 int portmod_xphy_device_op_mode_set(int unit, uint32 xphy_addr, uint32 device_op_mode)
    743 {
    744     int xphy_idx, rv;
    745     SOC_INIT_FUNC_DEFS;
    746 
    747     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    748     rv = XPHY_DEVICE_OP_MODE_SET(unit,_xphy_info[unit][xphy_idx], device_op_mode);
    749     _SOC_IF_ERR_EXIT(rv);
    750 
    751 exit:
    752     SOC_FUNC_RETURN;
    753 }
    754 
    755 int portmod_xphy_device_op_mode_get(int unit, uint32 xphy_addr, uint32* device_op_mode)
    756 {
    757     int xphy_idx, rv;
    758     SOC_INIT_FUNC_DEFS;
    759 
    760     _SOC_IF_ERR_EXIT(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    761     rv = XPHY_DEVICE_OP_MODE_GET(unit,_xphy_info[unit][xphy_idx], device_op_mode);
    762     _SOC_IF_ERR_EXIT(rv);
    763 
    764 exit:
    765     SOC_FUNC_RETURN;
    766 }
    767 
    768 int portmod_xphy_primary_core_num_set(int unit, uint32 xphy_addr, uint32 primary_core_num)
    769 {
    770     int xphy_idx, rv;
    771     SOC_INIT_FUNC_DEFS;
    772 
    773     SOC_IF_ERROR_RETURN(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    774     rv = XPHY_PRIMARY_CORE_NUM_SET(unit,_xphy_info[unit][xphy_idx], primary_core_num);
    775     _SOC_IF_ERR_EXIT(rv);
    776 
    777 exit:
    778     SOC_FUNC_RETURN;
    779 }
    780 
    781 int portmod_xphy_primary_core_num_get(int unit, uint32 xphy_addr, uint32* primary_core_num)
    782 {
    783     int xphy_idx, rv;
    784     SOC_INIT_FUNC_DEFS;
    785 
    786     SOC_IF_ERROR_RETURN(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    787     rv = XPHY_PRIMARY_CORE_NUM_GET(unit,_xphy_info[unit][xphy_idx], primary_core_num);
    788     _SOC_IF_ERR_EXIT(rv);
    789 
    790 exit:
    791     SOC_FUNC_RETURN;
    792 }
    793 
    794 int portmod_xphy_core_probed_set(int unit, uint32 xphy_addr, int core_probed)
    795 {
    796     int xphy_idx, rv;
    797     SOC_INIT_FUNC_DEFS;
    798 
    799     SOC_IF_ERROR_RETURN(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    800     rv = XPHY_CORE_PROBED_SET(unit,_xphy_info[unit][xphy_idx], core_probed);
    801     _SOC_IF_ERR_EXIT(rv);
    802 
    803 exit:
    804     SOC_FUNC_RETURN;
    805 }
    806 
    807 int portmod_xphy_core_probed_get(int unit, uint32 xphy_addr, int* core_probed)
    808 {
    809     int xphy_idx, rv;
    810     SOC_INIT_FUNC_DEFS;
    811 
    812     SOC_IF_ERROR_RETURN(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    813     rv = XPHY_CORE_PROBED_GET(unit,_xphy_info[unit][xphy_idx], core_probed);
    814     _SOC_IF_ERR_EXIT(rv);
    815 
    816 exit:
    817     SOC_FUNC_RETURN;
    818 }
    819 
    820 int portmod_xphy_active_lane_set (int unit, uint32 xphy_addr, uint32 active_lanes)
    821 {
    822     int xphy_idx, rv;
    823     SOC_INIT_FUNC_DEFS;
    824 
    825     SOC_IF_ERROR_RETURN(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    826     rv = XPHY_ACTIVE_LANES_SET(unit, _xphy_info[unit][xphy_idx], active_lanes)
    827     _SOC_IF_ERR_EXIT(rv);
    828 exit:
    829     SOC_FUNC_RETURN;
    830 }
    831 
    832 int portmod_xphy_active_lane_get (int unit, uint32 xphy_addr, uint32 *active_lanes)
    833 {
    834     int xphy_idx, rv;
    835     SOC_INIT_FUNC_DEFS;
    836 
    837     SOC_IF_ERROR_RETURN(_xphy_find_index(unit,xphy_addr,&xphy_idx));
    838     rv = XPHY_ACTIVE_LANES_GET(unit, _xphy_info[unit][xphy_idx], active_lanes)
    839     _SOC_IF_ERR_EXIT(rv);
    840 exit:
    841     SOC_FUNC_RETURN;
    842 }
    843 
    844 /*
    845  * This function is used to get the working operation mode from ext-phy.
    846  * It is mainly used to differ 1G pass thru mode and other modes like
    847  *pcs_repeater/retimer mode.
    848  */
    849 int portmod_port_phychain_operation_mode_get(int unit, int port, const phymod_phy_access_t* phy_access,
    850                                              const int chain_length,
    851                                              phymod_operation_mode_t* phy_op_mode)
    852 {
    853     int rv = PHYMOD_E_UNAVAIL;
    854     int phy_index;
    855     int is_legacy_phy = 0;
    856     phymod_operation_mode_t op_mode = phymodOperationModeRetimer;
    857 
    858     /* start from the most external phy. */
    859     phy_index = chain_length - 1;
    860 
    861     /* if it is external phy, check to see if it is legacy phy. */
    862     if (phy_index > 0) {
    863         rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
    864         if (rv != PHYMOD_E_NONE) return rv;
    865         if (is_legacy_phy) {
    866             rv = portmod_port_legacy_op_mode_get(unit, port, &op_mode);
    867         } else {
    868             if (phy_access[phy_index].access.lane_mask) {
    869                 rv = phymod_phy_op_mode_get(&phy_access[phy_index], &op_mode);
    870             } else {
    871                 rv = PHYMOD_E_UNAVAIL;
    872             }
    873         }
    874     } else {
    875         op_mode = phymodOperationModeCount;
    876     }
    877 
    878     *phy_op_mode = op_mode;
    879 
    880     return (rv);
    881 }
    882 
    883 int portmod_port_phychain_core_access_set(int unit, int phyn, int core_index, const phymod_core_access_t* core_access)
    884 {
    885     SOC_INIT_FUNC_DEFS;
    886 
    887     if (((1 + MAX_PHYN) <= phyn) || (0 >= phyn)){
    888         _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("phyn is out of the range of allowed external phys")));
    889     }
    890     if(NULL != _ext_phy_info[unit][phyn - 1][core_index]){
    891         sal_memcpy(&(_ext_phy_info[unit][phyn - 1][core_index]->core_access), core_access, sizeof(phymod_core_access_t));
    892     }
    893     
    894 exit:
    895     SOC_FUNC_RETURN; 
    896 
    897 }
    898 
    899 int portmod_port_phychain_core_access_get(int unit, int port, const int chain_length, int max_cores, phymod_core_access_t* core_access)
    900 {
    901     int phyn = 0;
    902     int nof_cores = 0;
    903     int is_most_ext = 0;
    904     SOC_INIT_FUNC_DEFS;
    905 
    906     if (((1 + MAX_PHYN) <= chain_length) || (0 >= chain_length)){
    907         _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("chain_length is out of the range of allowed external phys")));
    908     }
    909     for (phyn = 0; phyn < chain_length; phyn++) {
    910         _SOC_IF_ERR_EXIT(portmod_port_core_access_get(unit, port, phyn, max_cores, &core_access[phyn], &nof_cores, &is_most_ext));
    911     }
    912     
    913 exit:
    914     SOC_FUNC_RETURN; 
    915 }
    916 
    917 int portmod_port_phychain_core_probe(int unit, int port, phymod_core_access_t* core,
    918                                       const int chain_length)
    919 {
    920     int rv = PHYMOD_E_UNAVAIL;
    921     int phy_index;
    922     int phy_addr = 0x0;
    923     int is_phymod_probed=0;
    924     int is_legacy_phy = 0;
    925 
    926     PHYMOD_NULL_CHECK(core);
    927 
    928     /* Most EXT first. */
    929     phy_index = chain_length - 1;
    930 
    931     /* ALL PHYS */
    932     while(((rv == PHYMOD_E_NONE) || (rv == PHYMOD_E_UNAVAIL)) && (phy_index >= 0)) {
    933         /* currently portmod supports only one external phy (1(int) + 1(ext))
    934          * external phy is the outermost one. check for legacy ext phy if present */
    935         if (phy_index) {
    936             rv = phymod_core_probe(&(core[phy_index].access), &(core[phy_index].type), &is_phymod_probed);
    937 
    938             if ( (rv == PHYMOD_E_NONE) && (!is_phymod_probed) )
    939             {
    940                 if(portmod_port_legacy_phy_probe(unit, port))
    941                 {
    942                     is_legacy_phy = 1;
    943                     rv = portmod_xphy_is_legacy_phy_get(unit, core[phy_index].access.addr, &is_legacy_phy);
    944                     if (rv != PHYMOD_E_NONE) return rv;
    945                     /* Update the phy address in core access struct -- used by phy info */
    946                     phy_addr = portmod_port_legacy_phy_addr_get(unit, port);
    947                     core[phy_index].access.addr = phy_addr;
    948                     rv = PHYMOD_E_NONE;
    949                 }
    950             }
    951         } else {
    952             rv = phymod_core_probe( &(core[phy_index].access), &(core[phy_index].type), &is_phymod_probed);
    953         }
    954         phy_index--;
    955     }
    956 
    957     return(rv);
    958 }
    959 
    960 int portmod_port_phychain_core_identify (int unit, phymod_core_access_t* core,
    961                                           const int chain_length,
    962                                           uint32_t core_id,
    963                                           uint32_t* identified) 
    964 {
    965 int rv = PHYMOD_E_UNAVAIL;
    966     return(rv);
    967 }
    968 
    969 int portmod_port_phychain_core_lane_map_get(int unit ,const phymod_core_access_t* core,
    970                                             const int chain_length,
    971                                             phymod_lane_map_t* lane_map) 
    972 {
    973     int rv = PHYMOD_E_UNAVAIL;
    974     int phy_index;
    975     int is_legacy_phy = 0;
    976 
    977     PHYMOD_NULL_CHECK(core);
    978 
    979     /* Most EXT first. */
    980     phy_index = chain_length - 1;
    981 
    982     /* Most EXT */
    983     while( (PHYMOD_E_UNAVAIL == rv) && (phy_index >= 0)) {
    984         if (phy_index) {
    985             rv = portmod_xphy_is_legacy_phy_get(unit, core[phy_index].access.addr, &is_legacy_phy);
    986             if (rv != PHYMOD_E_NONE) return rv;
    987         }
    988         if (!is_legacy_phy) {
    989             rv = phymod_core_lane_map_get(&core[phy_index], lane_map); 
    990         }        
    991         phy_index--;
    992     }
    993     return(rv);
    994 }
    995 
    996 int portmod_port_phychain_core_reset_set(int unit, const phymod_core_access_t* core,
    997                                          const int chain_length,
    998                                          phymod_reset_mode_t reset_mode,
    999                                          phymod_reset_direction_t direction) 
   1000 {
   1001     int rv = PHYMOD_E_UNAVAIL;
   1002     int phy_index;
   1003     int is_legacy_phy = 0;
   1004     
   1005     PHYMOD_NULL_CHECK(core);
   1006 
   1007     /* Most EXT first. */
   1008     phy_index = chain_length - 1;
   1009 
   1010     /* ALL PHYS */
   1011     while(((rv == PHYMOD_E_NONE) || (rv == PHYMOD_E_UNAVAIL)) && (phy_index >= 0)) {
   1012         if (phy_index) {
   1013             rv = portmod_xphy_is_legacy_phy_get(unit, core[phy_index].access.addr, &is_legacy_phy);
   1014             if (rv != PHYMOD_E_NONE) return rv;
   1015         }
   1016         if (!is_legacy_phy) {
   1017             rv = phymod_core_reset_set(&core[phy_index], reset_mode, direction);
   1018         }
   1019         phy_index--;
   1020     }
   1021     return(rv);
   1022 }
   1023 
   1024 int portmod_port_phychain_core_reset_get(int unit, const phymod_core_access_t* core,
   1025                                          const int chain_length,
   1026                                          phymod_reset_mode_t reset_mode,
   1027                                          phymod_reset_direction_t* direction ) 
   1028 {
   1029     int rv = PHYMOD_E_UNAVAIL;
   1030     int phy_index;
   1031     int is_legacy_phy = 0;
   1032     
   1033     PHYMOD_NULL_CHECK(core);
   1034 
   1035     /* Most EXT first. */
   1036     phy_index = chain_length - 1;
   1037 
   1038     /* Most EXT */
   1039     while((rv == PHYMOD_E_UNAVAIL) && (phy_index >= 0)) {
   1040         if (phy_index) {
   1041             rv = portmod_xphy_is_legacy_phy_get(unit, core[phy_index].access.addr, &is_legacy_phy);
   1042             if (rv != PHYMOD_E_NONE) return rv;
   1043         }
   1044         if (!is_legacy_phy) {
   1045             rv = phymod_core_reset_get(&core[phy_index], reset_mode, direction);
   1046         }
   1047         phy_index--;
   1048     }
   1049 
   1050     return(rv);
   1051 }
   1052 
   1053 int portmod_port_phychain_core_firmware_info_get(int unit, const phymod_core_access_t* core,
   1054                                                  const int chain_length,
   1055                                                  phymod_core_firmware_info_t* fw_info) 
   1056 {
   1057     int rv = PHYMOD_E_UNAVAIL;
   1058     int phy_index;
   1059     int is_legacy_phy = 0;
   1060     
   1061     PHYMOD_NULL_CHECK(core);
   1062 
   1063     /* Most EXT first. */
   1064     phy_index = chain_length - 1;
   1065 
   1066     /* Most EXT */
   1067     while((PHYMOD_E_UNAVAIL == rv) && (phy_index >= 0)) {
   1068         if (phy_index) {
   1069             rv = portmod_xphy_is_legacy_phy_get(unit, core[phy_index].access.addr, &is_legacy_phy);
   1070             if (rv != PHYMOD_E_NONE) return rv;
   1071         }
   1072         if (!is_legacy_phy) {
   1073             rv = phymod_core_firmware_info_get(&core[phy_index], fw_info);
   1074         }
   1075         phy_index--;
   1076     }
   1077     return(rv);
   1078 }
   1079 
   1080 
   1081 int portmod_port_phychain_loopback_get(int unit, int port, const phymod_phy_access_t* phy_access,
   1082                                        const int chain_length,  
   1083                                        phymod_loopback_mode_t loopback, 
   1084                                        uint32_t *enable) 
   1085 {
   1086     int rv = PHYMOD_E_UNAVAIL;
   1087     int phy_index;
   1088     int is_legacy_phy = 0;
   1089     
   1090     PHYMOD_NULL_CHECK(phy_access);
   1091 
   1092     /* Most EXT first. */
   1093     phy_index = chain_length - 1;
   1094 
   1095     /* Most EXT */
   1096     while((PHYMOD_E_UNAVAIL == rv) && (phy_index >= 0)) {
   1097 
   1098         is_legacy_phy = 0;
   1099 
   1100         /* if it is external phy, check to see if it is legacy phy. */
   1101         if (phy_index > 0) {
   1102             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1103             if (rv != PHYMOD_E_NONE) return rv;
   1104         }
   1105 
   1106         if (is_legacy_phy) {
   1107             rv = portmod_port_legacy_loopback_get(unit, port, loopback, enable);
   1108 
   1109         } else {
   1110             if(phy_access[phy_index].access.lane_mask){
   1111                 rv = phymod_phy_loopback_get(&phy_access[phy_index], loopback, enable);
   1112             } else {
   1113                 rv = PHYMOD_E_NONE;
   1114             }
   1115         }
   1116         phy_index--; 
   1117     }
   1118     return(rv);
   1119 }
   1120 
   1121 int portmod_port_phychain_loopback_set(int unit, int port, const phymod_phy_access_t* phy_access,
   1122                                        const int chain_length,  
   1123                                        phymod_loopback_mode_t loopback, 
   1124                                        uint32_t enable) 
   1125 {
   1126     int rv = PHYMOD_E_UNAVAIL;
   1127     int phy_index;
   1128     int is_legacy_phy = 0;
   1129 
   1130     PHYMOD_NULL_CHECK(phy_access);
   1131 
   1132     /* Most EXT first. */
   1133     phy_index = chain_length - 1;
   1134 
   1135     
   1136     /* Loopback should be enabled always on the outermost phy */
   1137     /* Most EXT */
   1138     while((PHYMOD_E_UNAVAIL == rv) && (phy_index >= 0)) {
   1139 
   1140         is_legacy_phy = 0;
   1141 
   1142         /* if it is external phy, check to see if it is legacy phy. */
   1143         if (phy_index > 0) {
   1144             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1145             if (rv != PHYMOD_E_NONE) return rv;
   1146         }
   1147 
   1148         if (is_legacy_phy) {
   1149             rv = portmod_port_legacy_loopback_set(unit, port, loopback, enable);
   1150         } else {
   1151             if(phy_access[phy_index].access.lane_mask){
   1152                 rv = phymod_phy_loopback_set(&phy_access[phy_index], loopback, enable);
   1153             } else {
   1154                 rv = PHYMOD_E_NONE;
   1155             }
   1156 
   1157         }
   1158 
   1159         if (rv == PHYMOD_E_UNAVAIL) {
   1160             if (enable != 0){
   1161                 LOG_CLI((BSL_META_U(unit,
   1162                                  "phy_index=%d Loopback=%d Unavail - try next in chain\n"),
   1163                                   phy_index, loopback));
   1164            }
   1165         }
   1166         phy_index--;
   1167     }
   1168     return(rv);
   1169 }
   1170 
   1171 int portmod_port_phychain_firmware_core_config_set(int unit, const phymod_phy_access_t* phy_access,
   1172                                                    const int chain_length,
   1173                                                    phymod_firmware_core_config_t fw_core_config) 
   1174 {
   1175     int rv = PHYMOD_E_UNAVAIL;
   1176     int phy_index;
   1177     int is_legacy_phy = 0;
   1178     PHYMOD_NULL_CHECK(phy_access);
   1179 
   1180     /* start from the most external phy. */
   1181     phy_index = chain_length - 1;
   1182 
   1183     /* ALL PHYS */
   1184     while(((rv == PHYMOD_E_NONE) || (rv == PHYMOD_E_UNAVAIL)) && (phy_index >= 0)) {
   1185         if (phy_index){  
   1186             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1187             if (rv != PHYMOD_E_NONE) return rv;
   1188         }
   1189         if (!is_legacy_phy) {
   1190             rv = phymod_phy_firmware_core_config_set(&phy_access[phy_index], fw_core_config);
   1191         }
   1192         phy_index--;
   1193     }
   1194     return(rv);
   1195 }
   1196 
   1197 
   1198 int phymod_chain_phy_firmware_core_config_get(int unit, const phymod_phy_access_t* phy_access,
   1199                                               const int chain_length,
   1200                                               phymod_firmware_core_config_t *fw_core_config) 
   1201 {
   1202     int rv = PHYMOD_E_UNAVAIL;
   1203     int phy_index;
   1204     int is_legacy_phy = 0;
   1205     
   1206     /* start from the most external phy. */
   1207     phy_index = chain_length - 1;
   1208 
   1209     /* Most EXT */
   1210     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1211         if (phy_index){  
   1212             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1213             if (rv != PHYMOD_E_NONE) return rv;
   1214         }
   1215         if (!is_legacy_phy) {
   1216             rv = phymod_phy_firmware_core_config_get(&phy_access[phy_index], fw_core_config);
   1217         }
   1218         phy_index--;
   1219     }
   1220     return(rv);
   1221 }
   1222 
   1223 int portmod_port_phychain_firmware_lane_config_set(int unit, const phymod_phy_access_t* phy_access,
   1224                                                    const int chain_length,
   1225                                                    phymod_firmware_lane_config_t fw_lane_config)
   1226 {
   1227     int rv = PHYMOD_E_UNAVAIL;
   1228     int phy_index;
   1229     int is_legacy_phy = 0;
   1230     
   1231     /* start from the most external phy. */
   1232     phy_index = chain_length - 1;
   1233 
   1234     /* Most EXT */
   1235     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1236         if (phy_index){  
   1237             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1238             if (rv != PHYMOD_E_NONE) return rv;
   1239         }
   1240         if (!is_legacy_phy) {
   1241             rv = phymod_phy_firmware_lane_config_set(&phy_access[phy_index], fw_lane_config);
   1242         }
   1243         phy_index--;
   1244     }
   1245     return(rv);
   1246 }
   1247 
   1248 int portmod_port_phychain_firmware_lane_config_get(int unit, const phymod_phy_access_t* phy_access,
   1249                                                    const int chain_length,
   1250                                                    phymod_firmware_lane_config_t *fw_lane_config)
   1251 {
   1252     int rv = PHYMOD_E_UNAVAIL;
   1253     int phy_index;
   1254     int is_legacy_phy = 0;
   1255     
   1256     /* start from the most external phy. */
   1257     phy_index = chain_length - 1;
   1258                   
   1259     /* Most EXT */
   1260     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1261         if (phy_index){  
   1262             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1263             if (rv != PHYMOD_E_NONE) return rv;
   1264         }
   1265         if (!is_legacy_phy) {
   1266             rv = phymod_phy_firmware_lane_config_get(&phy_access[phy_index], fw_lane_config);
   1267         }
   1268         phy_index--;
   1269     }
   1270     return(rv);
   1271 }
   1272 
   1273 int portmod_port_phychain_core_pll_sequencer_restart(int unit, const phymod_core_access_t* core, 
   1274                                                      const int chain_length,
   1275                                                      uint32_t flags, 
   1276                                                      phymod_sequencer_operation_t operation)
   1277 {
   1278     int rv = PHYMOD_E_UNAVAIL;
   1279     int phy_index;
   1280     int is_legacy_phy = 0;
   1281     
   1282     /* start from the most external phy. */
   1283     phy_index = chain_length - 1;
   1284 
   1285     /* ALL PHYS */
   1286     while(((rv == PHYMOD_E_NONE) || (rv == PHYMOD_E_UNAVAIL)) && (phy_index >= 0)) {
   1287         if (phy_index){  
   1288             rv = portmod_xphy_is_legacy_phy_get(unit, core[phy_index].access.addr, &is_legacy_phy);
   1289             if (rv != PHYMOD_E_NONE) return rv;
   1290         }
   1291         if (!is_legacy_phy) {
   1292             rv = phymod_core_pll_sequencer_restart(&core[phy_index], flags, operation);
   1293         }
   1294         phy_index--;
   1295     }
   1296     return(rv);
   1297 }
   1298 
   1299 int phymod_chain_core_wait_event(int unit, const phymod_core_access_t* core, 
   1300                                  const int chain_length,
   1301                                  phymod_core_event_t event, 
   1302                                  uint32_t timeout) 
   1303 {
   1304     int rv = PHYMOD_E_UNAVAIL;
   1305     int phy_index;
   1306     int is_legacy_phy = 0;
   1307     
   1308     /* start from the most external phy. */
   1309     phy_index = chain_length - 1;
   1310 
   1311     /* Most EXT */
   1312     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1313         if (phy_index){  
   1314             rv = portmod_xphy_is_legacy_phy_get(unit, core[phy_index].access.addr, &is_legacy_phy);
   1315             if (rv != PHYMOD_E_NONE) return rv;
   1316         }
   1317         if (!is_legacy_phy) {
   1318             rv = phymod_core_wait_event(&core[phy_index], event, timeout);
   1319         }
   1320         phy_index--;
   1321     }
   1322     return(rv);
   1323 }
   1324 
   1325 int portmod_port_phychain_rx_restart(int unit, const phymod_phy_access_t* phy_access,
   1326                                      const int chain_length) 
   1327 {
   1328     int rv = PHYMOD_E_UNAVAIL;
   1329     int phy_index;
   1330     int is_legacy_phy = 0;
   1331     
   1332     /* start from the most external phy. */
   1333     phy_index = chain_length - 1;
   1334 
   1335     /* Most EXT */
   1336     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1337        if (phy_index){  
   1338            rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1339             if (rv != PHYMOD_E_NONE) return rv;
   1340         }
   1341         if (!is_legacy_phy) {
   1342             rv = phymod_phy_rx_restart(&phy_access[phy_index]);
   1343         }
   1344         phy_index--;
   1345     }
   1346     return(rv);
   1347 }
   1348 
   1349 int portmod_port_phychain_polarity_set(int unit, const phymod_phy_access_t* phy_access,
   1350                                        const int chain_length, 
   1351                                        const phymod_polarity_t* polarity) 
   1352 {
   1353     int rv = PHYMOD_E_UNAVAIL;
   1354     int phy_index;
   1355     int is_legacy_phy = 0;
   1356     
   1357     /* start from the most external phy. */
   1358     phy_index = chain_length - 1;
   1359 
   1360     /* Most EXT */
   1361     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1362         if (phy_index){  
   1363             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1364             if (rv != PHYMOD_E_NONE) return rv;
   1365         }
   1366         if (!is_legacy_phy) {
   1367             rv = phymod_phy_polarity_set(&phy_access[phy_index], polarity);
   1368         }
   1369         phy_index--;
   1370     }
   1371     return(rv);
   1372 }
   1373 
   1374 
   1375 int portmod_port_phychain_polarity_get(int unit, const phymod_phy_access_t* phy_access,
   1376                                        const int chain_length, 
   1377                                        phymod_polarity_t* polarity) 
   1378 {
   1379     int rv = PHYMOD_E_UNAVAIL;
   1380     int phy_index;
   1381     int is_legacy_phy = 0;
   1382     
   1383     /* start from the most external phy. */
   1384     phy_index = chain_length - 1;
   1385 
   1386     /* Most EXT */
   1387     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1388         if (phy_index){  
   1389             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1390             if (rv != PHYMOD_E_NONE) return rv;
   1391         }
   1392         if (!is_legacy_phy) {
   1393             rv = phymod_phy_polarity_get(&phy_access[phy_index], polarity);
   1394         }
   1395         phy_index--;
   1396     }
   1397     return(rv);
   1398 }
   1399 
   1400 int portmod_port_phychain_tx_set(int unit, const phymod_phy_access_t* phy_access,
   1401                                  const int chain_length,
   1402                                  const phymod_tx_t tx[]) 
   1403 {
   1404     int rv = PHYMOD_E_UNAVAIL;
   1405     int phy_index;
   1406     int i, port_start_lane=-1;
   1407     phymod_phy_access_t phy_acc_copy;
   1408     int is_legacy_phy = 0;
   1409 
   1410     /* start from the most external phy. */
   1411     phy_index = chain_length - 1;
   1412 
   1413     /* Most EXT */
   1414     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1415         is_legacy_phy = 0;
   1416 
   1417         /* if it is external phy, check to see if it is legacy phy. */
   1418         if (phy_index > 0) {
   1419             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1420             if (rv != PHYMOD_E_NONE) return rv;
   1421         }
   1422 
   1423         if (is_legacy_phy) {
   1424             rv = portmod_port_legacy_tx_set(phy_access, chain_length, tx); 
   1425         } else {
   1426             if(phy_access[phy_index].access.lane_mask){
   1427                 sal_memcpy(&phy_acc_copy, &phy_access[phy_index], sizeof(phy_acc_copy));
   1428                 /* set tx parameters for each lane of the core */
   1429                 for(i=0; i<PHYMOD_MAX_LANES_PER_CORE; i++){
   1430                     phy_acc_copy.access.lane_mask = 0x1 << i;
   1431                     if(phy_acc_copy.access.lane_mask & phy_access[phy_index].access.lane_mask){
   1432                         /* port_start_lane is the index of the very first lane of the current
   1433                          * core. port_start_lane is not always 0. However, the tx[] data always
   1434                          * starts from index 0. For instance, a Dino 40G port could have its
   1435                          * first lane at 0b00010000 in phy_access.access.lane_mask. In this
   1436                          * case, tx[0] should be given to this fifth lane instead of tx[4].
   1437                          */
   1438                         if (port_start_lane == -1){
   1439                             port_start_lane = i;
   1440                         }
   1441                         rv = phymod_phy_tx_set(&phy_acc_copy, &tx[i-port_start_lane]);
   1442                         SOC_IF_ERROR_RETURN(rv);
   1443                     }
   1444                 }
   1445             } else {
   1446                 rv = PHYMOD_E_NONE;
   1447             }
   1448         }
   1449         phy_index--; 
   1450     }
   1451     return(rv);
   1452 }
   1453 
   1454 int portmod_port_phychain_tx_get(int unit, const phymod_phy_access_t* phy_access,
   1455                                  const int chain_length,
   1456                                  phymod_tx_t* tx) 
   1457 {
   1458     int rv = PHYMOD_E_UNAVAIL;
   1459     int phy_index;
   1460     int i, port_start_lane=-1;
   1461     phymod_phy_access_t phy_acc_copy;
   1462     int is_legacy_phy = 0;
   1463 
   1464     /* start from the most external phy. */
   1465     phy_index = chain_length - 1;
   1466 
   1467     /* Most EXT */
   1468     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1469         if (phy_index){  
   1470             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1471             if (rv != PHYMOD_E_NONE) return rv;
   1472         }
   1473         if (!is_legacy_phy) {
   1474             if(phy_access[phy_index].access.lane_mask){
   1475                 sal_memcpy(&phy_acc_copy, &phy_access[phy_index], sizeof(phy_acc_copy));
   1476                 for(i=0; i<PHYMOD_MAX_LANES_PER_CORE; i++){
   1477                     phy_acc_copy.access.lane_mask = 0x1 << i;
   1478                     if(phy_acc_copy.access.lane_mask & phy_access[phy_index].access.lane_mask){
   1479                         /* See comments in portmod_port_phychain_tx_set for why there is a
   1480                          * discrepancy between lane_mask and tx[] in terms of lane index.
   1481                          */
   1482                         if (port_start_lane == -1){
   1483                             port_start_lane = i;
   1484                         }
   1485                         rv = phymod_phy_tx_get(&phy_acc_copy, &tx[i-port_start_lane]);
   1486                         if(rv!=PHYMOD_E_NONE){
   1487                             return rv;
   1488                         }
   1489                     }
   1490                 }
   1491             }
   1492         }
   1493         phy_index--;
   1494     }
   1495     return(rv);
   1496 }
   1497 
   1498 int portmod_port_phychain_media_type_tx_get(int unit, const phymod_phy_access_t* phy_access,
   1499                                            const int chain_length,
   1500                                            phymod_media_typed_t media, 
   1501                                            phymod_tx_t* tx) 
   1502 {
   1503     int rv = PHYMOD_E_UNAVAIL;
   1504     int phy_index;
   1505     int is_legacy_phy = 0;
   1506 
   1507     /* start from the most external phy. */
   1508     phy_index = chain_length - 1;
   1509 
   1510     /* Most EXT */
   1511     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1512         if (phy_index) {
   1513             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1514             if (rv != PHYMOD_E_NONE) return rv;
   1515         } 
   1516         if (!is_legacy_phy){
   1517             rv = phymod_phy_media_type_tx_get(&phy_access[phy_index], media, tx);
   1518         }
   1519         phy_index--;
   1520     }
   1521     return(rv);
   1522 }
   1523 
   1524 int portmod_port_phychain_tx_override_set(int unit, const phymod_phy_access_t* phy_access,
   1525                                           const int chain_length,
   1526                                           const phymod_tx_override_t* tx_override) 
   1527 {
   1528     int rv = PHYMOD_E_UNAVAIL;
   1529     int phy_index;
   1530     int is_legacy_phy = 0;
   1531 
   1532     /* start from the most external phy. */
   1533     phy_index = chain_length - 1;
   1534 
   1535     /* Most EXT */
   1536     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1537         if (phy_index){  
   1538             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1539             if (rv != PHYMOD_E_NONE) return rv;
   1540         }
   1541         if (!is_legacy_phy) {
   1542             rv = phymod_phy_tx_override_set(&phy_access[phy_index], tx_override);
   1543         }
   1544         phy_index--;
   1545     }
   1546     return(rv);
   1547 }
   1548 
   1549 int portmod_port_phychain_tx_override_get(int unit, const phymod_phy_access_t* phy_access,
   1550                                           const int chain_length,
   1551                                           phymod_tx_override_t* tx_override) 
   1552 {
   1553     int rv = PHYMOD_E_UNAVAIL;
   1554     int phy_index;
   1555     int is_legacy_phy = 0;
   1556     
   1557     /* start from the most external phy. */
   1558     phy_index = chain_length - 1;
   1559 
   1560     /* Most EXT */
   1561     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1562         if (phy_index){  
   1563             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1564             if (rv != PHYMOD_E_NONE) return rv;
   1565         }
   1566         if (!is_legacy_phy) {
   1567             rv = phymod_phy_tx_override_get(&phy_access[phy_index], tx_override);
   1568         }
   1569         phy_index--;
   1570     }
   1571     return(rv);
   1572 }
   1573 
   1574 int portmod_port_phychain_txpi_config_set(int unit, const phymod_phy_access_t* phy_access,
   1575                                           const int chain_length,
   1576                                           const phymod_txpi_config_t* config)
   1577 {
   1578     int rv = PHYMOD_E_UNAVAIL;
   1579     int phy_index;
   1580     int is_legacy_phy = 0;
   1581 
   1582     /* start from the most external phy. */
   1583     phy_index = chain_length - 1;
   1584 
   1585     /* Most EXT */
   1586     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1587         if (phy_index){
   1588             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1589             if (rv != PHYMOD_E_NONE) return rv;
   1590         }
   1591         if (!is_legacy_phy) {
   1592             rv = phymod_phy_txpi_config_set(&phy_access[phy_index], config);
   1593         }
   1594         phy_index--;
   1595     }
   1596     return(rv);
   1597 }
   1598 
   1599 int portmod_port_phychain_txpi_config_get(int unit, const phymod_phy_access_t* phy_access,
   1600                                           const int chain_length,
   1601                                           phymod_txpi_config_t* config)
   1602 {
   1603     int rv = PHYMOD_E_UNAVAIL;
   1604     int phy_index;
   1605     int is_legacy_phy = 0;
   1606 
   1607     /* start from the most external phy. */
   1608     phy_index = chain_length - 1;
   1609 
   1610     /* Most EXT */
   1611     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1612         if (phy_index){
   1613             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1614             if (rv != PHYMOD_E_NONE) return rv;
   1615         }
   1616         if (!is_legacy_phy) {
   1617             rv = phymod_phy_txpi_config_get(&phy_access[phy_index], config);
   1618         }
   1619         phy_index--;
   1620     }
   1621     return(rv);
   1622 }
   1623 
   1624 int portmod_port_phychain_rx_set(int unit, const phymod_phy_access_t* phy_access,
   1625                                  const int chain_length,
   1626                                  const phymod_rx_t* rx) 
   1627 {
   1628     int rv = PHYMOD_E_UNAVAIL;
   1629     int phy_index;
   1630     int is_legacy_phy = 0;
   1631 
   1632     /* start from the most external phy. */
   1633     phy_index = chain_length - 1;
   1634 
   1635     /* Most EXT */
   1636     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1637         if (phy_index){  
   1638             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1639             if (rv != PHYMOD_E_NONE) return rv;
   1640         }
   1641         if (!is_legacy_phy) {
   1642             rv = phymod_phy_rx_set(&phy_access[phy_index], rx);
   1643         }
   1644         phy_index--;
   1645     }
   1646     return(rv);
   1647 }
   1648 
   1649 int portmod_port_phychain_rx_get(int unit, const phymod_phy_access_t* phy_access,
   1650                                  const int chain_length,
   1651                                  phymod_rx_t* rx) 
   1652 {
   1653     int rv = PHYMOD_E_UNAVAIL;
   1654     int phy_index;
   1655     int is_legacy_phy = 0;
   1656 
   1657     /* start from the most external phy. */
   1658     phy_index = chain_length - 1;
   1659 
   1660     /* Most EXT */
   1661     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1662         if (phy_index){  
   1663             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1664             if (rv != PHYMOD_E_NONE) return rv;
   1665         }
   1666         if (!is_legacy_phy) {
   1667             if (phy_index && (phy_access[phy_index].access.lane_mask == 0)) {
   1668                 rv = PHYMOD_E_NONE; 
   1669             } else { 
   1670                 rv = phymod_phy_rx_get(&phy_access[phy_index], rx);
   1671             }
   1672         }
   1673         phy_index--;
   1674     }
   1675     return(rv);
   1676 }
   1677 
   1678 int portmod_port_phychain_reset_set(int unit, int port, const phymod_phy_access_t* phy_access,
   1679                                     const int chain_length,
   1680                                     const phymod_phy_reset_t* reset) 
   1681 {
   1682     int rv = PHYMOD_E_UNAVAIL;
   1683     int phy_index;
   1684     int is_legacy_phy = 0;
   1685 
   1686     /* start from the most external phy. */
   1687     phy_index = chain_length - 1;
   1688 
   1689     /* Most EXT */
   1690     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1691 
   1692         is_legacy_phy = 0;
   1693 
   1694         /* if it is external phy, check to see if it is legacy phy. */
   1695         if (phy_index > 0) {
   1696             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1697             if (rv != PHYMOD_E_NONE) return rv;
   1698         }
   1699 
   1700              
   1701         if (is_legacy_phy) {
   1702                 rv = portmod_port_legacy_phy_reset_set(unit, port);
   1703         } else {
   1704             if((phy_access[phy_index].access.lane_mask == 0) && phy_index) {
   1705                 rv = PHYMOD_E_NONE;
   1706             } else {
   1707                 rv = phymod_phy_reset_set(&phy_access[phy_index], reset);
   1708             }
   1709         }
   1710         phy_index--; 
   1711     }
   1712     return(rv);
   1713 }
   1714 
   1715 int portmod_port_phychain_reset_get(int unit, const phymod_phy_access_t* phy_access,
   1716                                     const int chain_length,
   1717                                     phymod_phy_reset_t* reset) 
   1718 {
   1719     int rv = PHYMOD_E_UNAVAIL;
   1720     int phy_index;
   1721     int is_legacy_phy = 0;
   1722     
   1723     /* start from the most external phy. */
   1724     phy_index = chain_length - 1;
   1725 
   1726     /* Most EXT */
   1727     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1728         if (phy_index){  
   1729             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1730             if (rv != PHYMOD_E_NONE) return rv;
   1731         }
   1732         if (!is_legacy_phy) {
   1733             rv = phymod_phy_reset_get(&phy_access[phy_index], reset);
   1734         }
   1735         phy_index--;
   1736     }
   1737     return(rv);
   1738 }
   1739 
   1740 int portmod_port_phychain_power_set(int unit, int port, const phymod_phy_access_t* phy_access,
   1741                                     const int chain_length, uint32 flags,
   1742                                     const phymod_phy_power_t* power) 
   1743 {
   1744     int rv = PHYMOD_E_UNAVAIL;
   1745     int phy_index;
   1746     int is_legacy_phy = 0;
   1747 
   1748     /* start from the most external phy. */
   1749     phy_index = chain_length - 1;
   1750 
   1751     if (flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) {
   1752         return  phymod_phy_power_set(&phy_access[0], power);
   1753     }
   1754     
   1755     /* Most EXT */
   1756     while((PHYMOD_E_UNAVAIL == rv) && (phy_index >= 0)) {
   1757         is_legacy_phy = 0;
   1758 
   1759         /* if it is external phy, check to see if it is legacy phy. */
   1760         if (phy_index > 0) {
   1761             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1762             if (rv != PHYMOD_E_NONE) return rv;
   1763         }
   1764 
   1765         if (is_legacy_phy) {
   1766             rv = portmod_port_legacy_power_set(unit, port, power); 
   1767         } else {
   1768             if(phy_access[phy_index].access.lane_mask){
   1769                 rv = phymod_phy_power_set(&phy_access[phy_index], power);
   1770             } else {
   1771                 rv = PHYMOD_E_NONE;
   1772             }
   1773         }
   1774         phy_index--; 
   1775     }
   1776     return(rv);
   1777 }
   1778 
   1779 int portmod_port_phychain_power_get(int unit, int port,  const phymod_phy_access_t* phy_access,
   1780                                     const int chain_length, uint32 flags,
   1781                                     phymod_phy_power_t* power) 
   1782 {
   1783     int rv = PHYMOD_E_UNAVAIL;
   1784     int phy_index;
   1785     int is_legacy_phy = 0;
   1786 
   1787     /* start from the most external phy. */
   1788     phy_index = chain_length - 1;
   1789 
   1790     if (flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) {
   1791         return  phymod_phy_power_get(&phy_access[0], power);
   1792     }
   1793     
   1794     /* Most EXT */
   1795     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1796         is_legacy_phy = 0;
   1797 
   1798         /* if it is external phy, check to see if it is legacy phy. */
   1799         if (phy_index > 0) {
   1800             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1801             if (rv != PHYMOD_E_NONE) return rv;
   1802         }
   1803 
   1804         if (is_legacy_phy) {
   1805             rv = portmod_port_legacy_power_get(unit, port, power); 
   1806         } else {
   1807             if(phy_access[phy_index].access.lane_mask){
   1808                 rv = phymod_phy_power_get(&phy_access[phy_index], power);
   1809             } else {
   1810                 rv = PHYMOD_E_NONE;
   1811             }
   1812 
   1813         }
   1814         phy_index--;
   1815     }
   1816     return(rv);
   1817 }
   1818 
   1819 int portmod_port_phychain_tx_lane_control_set(int unit, int port, const phymod_phy_access_t* phy_access,
   1820                                               const int chain_length, uint32 flags,
   1821                                               phymod_phy_tx_lane_control_t tx_control) 
   1822 {
   1823     int rv = PHYMOD_E_UNAVAIL;
   1824     int phy_index;
   1825     int is_legacy_phy = 0;
   1826 
   1827     /* start from the most external phy. */
   1828     phy_index = chain_length - 1;
   1829 
   1830     if (flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) {
   1831         return  phymod_phy_tx_lane_control_set(&phy_access[0], tx_control);
   1832     }
   1833 
   1834     /* Most EXT */
   1835     /* Program only the outer most phy */
   1836     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1837 
   1838         is_legacy_phy = 0;
   1839 
   1840         /* if it is external phy, check to see if it is legacy phy. */
   1841         if (phy_index > 0) {
   1842             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1843             if (rv != PHYMOD_E_NONE) return rv;
   1844         }
   1845 
   1846         if (is_legacy_phy) {
   1847             rv = portmod_port_legacy_tx_ln_ctrl_set(unit, port, &tx_control);           
   1848         } else {
   1849             if(phy_access[phy_index].access.lane_mask){
   1850                 rv = phymod_phy_tx_lane_control_set(&phy_access[phy_index], tx_control);
   1851             } else {
   1852                 rv = PHYMOD_E_NONE;
   1853             }
   1854 
   1855         }
   1856         phy_index--;
   1857     }
   1858     return(rv);
   1859 }
   1860 
   1861 int portmod_port_phychain_tx_lane_control_get(int unit, int port, const phymod_phy_access_t* phy_access,
   1862                                               const int chain_length, uint32 flags,
   1863                                               phymod_phy_tx_lane_control_t *tx_control) 
   1864 {
   1865     int rv = PHYMOD_E_UNAVAIL;
   1866     int phy_index;
   1867     int is_legacy_phy = 0;
   1868 
   1869     /* start from the most external phy. */
   1870     phy_index = chain_length - 1;
   1871 
   1872     
   1873     if (flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) {
   1874         return  phymod_phy_tx_lane_control_get(&phy_access[0], tx_control);
   1875     }
   1876     
   1877     /* Most EXT */
   1878     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1879 
   1880         is_legacy_phy = 0;
   1881 
   1882         /* if it is external phy, check to see if it is legacy phy. */
   1883         if (phy_index > 0) {
   1884             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1885             if (rv != PHYMOD_E_NONE) return rv;
   1886         }
   1887 
   1888         if (is_legacy_phy) {
   1889                 rv = portmod_port_legacy_tx_ln_ctrl_get(unit, port, tx_control);
   1890         } else {
   1891             if(phy_access[phy_index].access.lane_mask){
   1892                 rv = phymod_phy_tx_lane_control_get(&phy_access[phy_index], tx_control);
   1893             } else {
   1894                 rv = PHYMOD_E_NONE;
   1895             }
   1896             return rv;
   1897         }
   1898         /*
   1899          * COVERITY
   1900          *
   1901          * This default is unreachable. It is kept intentionally as a defensive default for future
   1902          * development.
   1903          */
   1904         /* coverity[unreachable] */
   1905         phy_index--;
   1906     }
   1907     return(rv);
   1908 }
   1909 
   1910 int portmod_port_phychain_rx_lane_control_set(int unit, int port, const phymod_phy_access_t* phy_access,
   1911                                               const int chain_length, uint32 flags,
   1912                                               phymod_phy_rx_lane_control_t rx_control)
   1913 {
   1914     int rv = PHYMOD_E_UNAVAIL;
   1915     int phy_index;
   1916     int is_legacy_phy = 0;
   1917 
   1918     /* start from the most external phy. */
   1919     phy_index = chain_length - 1;
   1920 
   1921     if (flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) {
   1922         return phymod_phy_rx_lane_control_set(&phy_access[0], rx_control);
   1923     }
   1924     
   1925     /* Most EXT */
   1926     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1927         is_legacy_phy = 0;
   1928 
   1929         /* if it is external phy, check to see if it is legacy phy. */
   1930         if (phy_index > 0) {
   1931             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1932             if (rv != PHYMOD_E_NONE) return rv;
   1933         }
   1934 
   1935         if (is_legacy_phy) {
   1936             rv = portmod_port_legacy_rx_ln_ctrl_set(unit, port, &rx_control);               
   1937         } else {
   1938             if(phy_access[phy_index].access.lane_mask){
   1939                 rv = phymod_phy_rx_lane_control_set(&phy_access[phy_index], rx_control);
   1940             } else {
   1941                 rv = PHYMOD_E_NONE;
   1942             }
   1943         }
   1944         phy_index--;
   1945     }
   1946     return(rv);
   1947 }
   1948 
   1949 int portmod_port_phychain_rx_lane_control_get(int unit, int port, const phymod_phy_access_t* phy_access,
   1950                                               const int chain_length, uint32 flags,
   1951                                               phymod_phy_rx_lane_control_t *rx_control)
   1952 {
   1953     int rv = PHYMOD_E_UNAVAIL;
   1954     int phy_index;
   1955     int is_legacy_phy = 0;
   1956 
   1957     /* start from the most external phy. */
   1958     phy_index = chain_length - 1;
   1959 
   1960     if (flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) {
   1961         return phymod_phy_rx_lane_control_get(&phy_access[0], rx_control);
   1962     }
   1963 
   1964     /* Most EXT */
   1965     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   1966         is_legacy_phy = 0;
   1967 
   1968         /* if it is external phy, check to see if it is legacy phy. */
   1969         if (phy_index > 0) {
   1970             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   1971             if (rv != PHYMOD_E_NONE) return rv;
   1972         }
   1973 
   1974         if (is_legacy_phy) {
   1975             rv = portmod_port_legacy_rx_ln_ctrl_get(unit, port, rx_control);                 
   1976         } else {
   1977             if ((phy_access[phy_index].access.lane_mask == 0) && phy_index) {
   1978                 rv = PHYMOD_E_NONE;
   1979             } else {
   1980                 rv = phymod_phy_rx_lane_control_get(&phy_access[phy_index], rx_control);
   1981             }
   1982             return rv;
   1983         }
   1984         /*
   1985          * COVERITY
   1986          *
   1987          * This default is unreachable. It is kept intentionally as a defensive default for future
   1988          * development.
   1989          */
   1990         /* coverity[unreachable] */
   1991         phy_index--;
   1992     }
   1993     return(rv);
   1994 }
   1995 
   1996 int portmod_port_phychain_fec_enable_set(int unit, int port, const phymod_phy_access_t* phy_access,
   1997                                          const int chain_length, uint32 flags,
   1998                                          uint32_t enable) 
   1999 {
   2000     int rv = PHYMOD_E_UNAVAIL;
   2001     int phy_index;
   2002     int is_legacy_phy = 0;
   2003     
   2004     /* start from the most external phy. */
   2005     phy_index = chain_length - 1;
   2006 
   2007     if (flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) {
   2008         return phymod_phy_fec_enable_set(&phy_access[0], enable);
   2009     }
   2010 
   2011     /* Most EXT */
   2012     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2013         is_legacy_phy = 0;
   2014 
   2015         /* if it is external phy, check to see if it is legacy phy. */
   2016         if (phy_index > 0) {
   2017             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2018             if (rv != PHYMOD_E_NONE) return rv;
   2019         }
   2020 
   2021         if (is_legacy_phy) {
   2022             rv = portmod_port_legacy_fec_set(unit, port, enable);
   2023             return rv;
   2024         } else {
   2025             rv = phymod_phy_fec_enable_set(&phy_access[phy_index], enable); 
   2026             return rv;
   2027         }
   2028 
   2029         /*
   2030          * COVERITY
   2031          *
   2032          * This default is unreachable. It is kept intentionally as a defensive default for future
   2033          * development.
   2034          */
   2035         /* coverity[unreachable] */
   2036         phy_index--;
   2037     }
   2038     return(rv);
   2039 }
   2040 
   2041 int portmod_port_phychain_fec_enable_get(int unit, int port, const phymod_phy_access_t* phy_access,
   2042                                          const int chain_length, uint32 flags,
   2043                                          uint32_t *enable) 
   2044 {
   2045     int rv = PHYMOD_E_UNAVAIL;
   2046     int phy_index;
   2047     int is_legacy_phy = 0;
   2048     
   2049     /* start from the most external phy. */
   2050     phy_index = chain_length - 1;
   2051 
   2052     if (flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) {
   2053         return phymod_phy_fec_enable_get(&phy_access[0], enable);
   2054     }
   2055 
   2056     /* Most EXT */
   2057     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2058         is_legacy_phy = 0;
   2059 
   2060         /* if it is external phy, check to see if it is legacy phy. */
   2061         if (phy_index > 0) {
   2062             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2063             if (rv != PHYMOD_E_NONE) return rv;
   2064         }
   2065 
   2066         if (is_legacy_phy) {
   2067             rv = portmod_port_legacy_fec_get(unit, port, enable);
   2068             return rv;
   2069         } else {
   2070             rv = phymod_phy_fec_enable_get(&phy_access[phy_index], enable); 
   2071             return rv;
   2072         }
   2073         /*
   2074          * COVERITY
   2075          *
   2076          * This default is unreachable. It is kept intentionally as a defensive default for future
   2077          * development.
   2078          */
   2079         /* coverity[unreachable] */
   2080         phy_index--;
   2081     }
   2082     return(rv);
   2083 }
   2084 
   2085 int portmod_port_phychain_eee_set(int unit, int port, const phymod_phy_access_t* phy_access,
   2086                                   const int chain_length,
   2087                                   uint32_t enable) 
   2088 {
   2089     int rv = PHYMOD_E_UNAVAIL;
   2090     int phy_index;
   2091     int is_legacy_phy = 0;
   2092 
   2093     /* start from the most external phy. */
   2094     phy_index = chain_length - 1;
   2095 
   2096     /* Most EXT */
   2097     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2098 
   2099         is_legacy_phy = 0;
   2100 
   2101         /* if it is external phy, check to see if it is legacy phy. */
   2102         if (phy_index > 0) {
   2103             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2104             if (rv != PHYMOD_E_NONE) return rv;
   2105         }
   2106 
   2107         if (is_legacy_phy) {
   2108             rv = portmod_port_legacy_eee_set(unit, port, enable); 
   2109             return rv; 
   2110         } else {
   2111             rv = phymod_phy_eee_set(&phy_access[phy_index], enable); 
   2112             return rv;
   2113         }
   2114         /*
   2115          * COVERITY
   2116          *
   2117          * This default is unreachable. It is kept intentionally as a defensive default for future
   2118          * development.
   2119          */
   2120         /* coverity[unreachable] */
   2121         phy_index--;
   2122     }
   2123     return(rv);
   2124 }
   2125 
   2126 int portmod_port_phychain_eee_get(int unit, int port, const phymod_phy_access_t* phy_access,
   2127                                   const int chain_length,
   2128                                   uint32_t *enable)
   2129 {
   2130     int rv = PHYMOD_E_UNAVAIL;
   2131     int phy_index;
   2132     int is_legacy_phy = 0;
   2133 
   2134     /* start from the most external phy. */
   2135     phy_index = chain_length - 1;
   2136 
   2137     /* Most EXT */
   2138     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2139         is_legacy_phy = 0;
   2140 
   2141         /* if it is external phy, check to see if it is legacy phy. */
   2142         if (phy_index > 0) {
   2143             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2144             if (rv != PHYMOD_E_NONE) return rv;
   2145         }
   2146 
   2147         if (is_legacy_phy) {
   2148             rv = portmod_port_legacy_eee_get(unit, port, enable);
   2149             return rv;
   2150         } else {
   2151             rv = phymod_phy_eee_get(&phy_access[phy_index], enable); 
   2152             return rv;
   2153         }
   2154         /*
   2155          * COVERITY
   2156          *
   2157          * This default is unreachable. It is kept intentionally as a defensive default for future
   2158          * development.
   2159          */
   2160         /* coverity[unreachable] */
   2161         phy_index--;
   2162     }
   2163     return(rv);
   2164 }
   2165 
   2166 int portmod_port_phychain_interface_config_set(int unit, int port, const phymod_phy_access_t* phy_access,
   2167                                                const int chain_length,
   2168                                                uint32_t flags,
   2169                                                const phymod_phy_inf_config_t* config,
   2170                                                phymod_interface_t serdes_interface,
   2171                                                int ref_clk, 
   2172                                                const uint32 phy_init_flags)
   2173 {
   2174     int rv = PHYMOD_E_NONE;
   2175     int phy_index;
   2176     phymod_phy_inf_config_t int_config = *(phymod_phy_inf_config_t*)config;
   2177     phymod_autoneg_control_t an;
   2178     uint32_t an_done;
   2179     int is_legacy_phy = 0;
   2180     soc_port_if_t interface = SOC_PORT_IF_NULL;
   2181     SOC_INIT_FUNC_DEFS;
   2182 
   2183     /* start from the most external phy. */
   2184     phy_index = chain_length - 1;
   2185 
   2186     if(phy_init_flags == PORTMOD_INIT_F_ALL_PHYS) { 
   2187         /* ALL PHYS */
   2188         while(((rv == PHYMOD_E_NONE) || (rv == PHYMOD_E_UNAVAIL)) && (phy_index >= 0)) {
   2189 
   2190             is_legacy_phy = 0;
   2191 
   2192             /* if it is external phy, check to see if it is legacy phy. */
   2193             if (phy_index > 0) {
   2194                 rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2195                 if (rv != PHYMOD_E_NONE) return rv;
   2196             }
   2197 
   2198             if (is_legacy_phy) {
   2199                 if (flags & PHYMOD_INTF_F_UPDATE_SPEED_LINKUP) {
   2200                     rv = portmod_port_legacy_an_get(unit, port, &an, &an_done);
   2201                     if (rv != PHYMOD_E_NONE) {
   2202                         return rv;
   2203                     }
   2204                     if (an.enable) {
   2205                         phy_index--;
   2206                         continue;
   2207                     }
   2208                 }
   2209                 rv = portmod_port_legacy_interface_config_set(unit, port, config);
   2210             } else {
   2211                 if (phy_access[phy_index].access.lane_mask) {
   2212                     if (flags & PHYMOD_INTF_F_UPDATE_SPEED_LINKUP){
   2213                         rv = phymod_phy_autoneg_get(&phy_access[phy_index], &an, &an_done);
   2214                         if (rv != PHYMOD_E_NONE) {
   2215                             return rv;
   2216                         }
   2217                         if (an.enable) {
   2218                             phy_index--;
   2219                             continue;
   2220                         }
   2221                     }
   2222                     if (phy_index < (chain_length-1)) {
   2223                         if ((serdes_interface != phymodInterfaceCount) && (phy_index == 0)) {
   2224                             /* if user specify the serdes_interface, it will get priority. */
   2225                             int_config.interface_type = serdes_interface;
   2226 
   2227                             /* update the medium type within interface_mode according to the new interface type */
   2228                             _SOC_IF_ERR_EXIT(portmod_intf_from_phymod_intf(unit, serdes_interface, &interface));
   2229                             _SOC_IF_ERR_EXIT(portmod_media_type_from_port_intf(unit, interface, &int_config));
   2230                         } else {
   2231                             rv = portmod_port_line_to_sys_intf_map(unit, &phy_access[phy_index+1], &phy_access[phy_index], port,
   2232                                            config, ref_clk, phy_init_flags,
   2233                                            int_config.interface_type, &int_config.interface_type);
   2234                         }
   2235                         if (rv) return (rv);
   2236                     }
   2237                     rv = phymod_phy_interface_config_set(&phy_access[phy_index], flags, &int_config);
   2238                 } 
   2239             }
   2240             phy_index--;
   2241         }
   2242     } else if (phy_init_flags == PORTMOD_INIT_F_EXTERNAL_MOST_ONLY) {
   2243         /* Most EXT, reprogram the internal and intermediate phy with existing setting. */
   2244         while((PHYMOD_E_NONE == rv) && (phy_index >= 0)) {
   2245 
   2246             is_legacy_phy = 0;
   2247 
   2248             /* if it is external phy, check to see if it is legacy phy. */
   2249             if (phy_index > 0) {
   2250                 rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2251                 if (rv != PHYMOD_E_NONE) return rv;
   2252             }
   2253 
   2254             if (is_legacy_phy) {
   2255                 rv = portmod_port_legacy_interface_config_set(unit, port, config);
   2256             } else {
   2257                 if ((phy_index == (chain_length - 1)) || (!(flags & PHYMOD_INTF_F_SET_SPD_NO_TRIGGER))) {
   2258                     if (phy_index < (chain_length-1)) {
   2259                         if ((serdes_interface != phymodInterfaceCount) && (phy_index == 0)) {
   2260                             /* if user specify the serdes_interface, it will get priority. */
   2261                             int_config.interface_type = serdes_interface;
   2262 
   2263                             /* update the medium type within interface_mode according to the new interface type */
   2264                             _SOC_IF_ERR_EXIT(portmod_intf_from_phymod_intf(unit, serdes_interface, &interface));
   2265                             _SOC_IF_ERR_EXIT(portmod_media_type_from_port_intf(unit, interface, &int_config));
   2266                         } else {
   2267                             rv = portmod_port_line_to_sys_intf_map(unit, &phy_access[phy_index+1], &phy_access[phy_index], port,
   2268                                            config, ref_clk, phy_init_flags,
   2269                                            int_config.interface_type, &int_config.interface_type);
   2270                         }
   2271                         if (rv) return (rv);
   2272                     }
   2273 
   2274                     if(phy_access[phy_index].access.lane_mask){
   2275                         rv = phymod_phy_interface_config_set(&phy_access[phy_index], flags, &int_config);
   2276                     }
   2277                 }
   2278             }
   2279             phy_index--;
   2280         }
   2281     } else if (phy_init_flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) {
   2282         while(phy_index >= 0) {
   2283             if (phy_index < (chain_length-1)) {
   2284                 if ((serdes_interface != phymodInterfaceCount) && (phy_index == 0)) {
   2285                     /* if user specify the serdes_interface, it will get priority. */ 
   2286                     int_config.interface_type = serdes_interface; 
   2287 
   2288                     /* update the medium type within interface_mode according to the new interface type */
   2289                     _SOC_IF_ERR_EXIT(portmod_intf_from_phymod_intf(unit, serdes_interface, &interface));
   2290                     _SOC_IF_ERR_EXIT(portmod_media_type_from_port_intf(unit, interface, &int_config));
   2291                 } else {
   2292                     rv = portmod_port_line_to_sys_intf_map(unit, &phy_access[phy_index+1], &phy_access[phy_index], port,
   2293                                    config, ref_clk, phy_init_flags,
   2294                                    int_config.interface_type, &int_config.interface_type);
   2295                 }
   2296                 if (rv) return (rv);
   2297             }
   2298             phy_index--;
   2299         }
   2300         rv = phymod_phy_interface_config_set(&phy_access[0], flags, &int_config);
   2301     }
   2302     return(rv);
   2303 
   2304 exit:
   2305     SOC_FUNC_RETURN;
   2306 }
   2307 
   2308 int portmod_port_phychain_interface_config_get(int unit, int port, const phymod_phy_access_t* phy_access,
   2309                                   const int chain_length,
   2310                                   uint32_t flags,
   2311                                   phymod_ref_clk_t ref_clock,
   2312                                   phymod_phy_inf_config_t* config,
   2313                                   const uint32 phy_init_flags)
   2314 {
   2315     int rv = PHYMOD_E_UNAVAIL;
   2316     int phy_index;
   2317     int is_legacy_phy = 0;
   2318     phymod_operation_mode_t op_mode = phymodOperationModeRetimer;
   2319     int interface_available = 1;
   2320 
   2321     /* start from the most external phy. */
   2322     phy_index = chain_length - 1;
   2323 
   2324     
   2325     if (phy_init_flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) {
   2326         return phymod_phy_interface_config_get(&phy_access[0], flags, ref_clock, config); 
   2327     }
   2328 
   2329     /* Most EXT */
   2330     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2331 
   2332         is_legacy_phy = 0;
   2333 
   2334         /* if it is external phy, check to see if it is legacy phy. */
   2335         if (phy_index > 0) {
   2336             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2337             if (rv != PHYMOD_E_NONE) return rv;
   2338         }
   2339 
   2340         if (is_legacy_phy) {
   2341             rv = portmod_port_legacy_interface_config_get(unit, port, config);
   2342             return rv;
   2343         } else {
   2344             if ((phy_access[phy_index].access.lane_mask == 0) & phy_index) {
   2345                 rv = PHYMOD_E_NONE;
   2346             } else {
   2347                 /*
   2348                  * If external phy, check to see if it is in Passthru mode,  get
   2349                  * the interface information only when it is not in Passthru mode.
   2350                  * Otherwise, back off to the internal serdes.
   2351                  */
   2352 
   2353                 interface_available = TRUE;
   2354                 if(phy_index){
   2355                     rv = phymod_phy_op_mode_get(&phy_access[phy_index], &op_mode);
   2356                     if ((rv == PHYMOD_E_NONE) && (op_mode == phymodOperationModePassthru)) {
   2357                         interface_available = FALSE;
   2358                     } 
   2359                 }
   2360 
   2361                 if (interface_available){ 
   2362                     rv = phymod_phy_interface_config_get(&phy_access[phy_index], flags, ref_clock, config);
   2363                 } else {
   2364                     rv = PHYMOD_E_UNAVAIL;
   2365                 }
   2366             }
   2367         }
   2368         /*
   2369          * COVERITY
   2370          *
   2371          * This default is unreachable. It is kept intentionally as a defensive default for future
   2372          * development.
   2373          */
   2374         /* coverity[unreachable] */
   2375         phy_index--;
   2376     }
   2377     return(rv);
   2378 }
   2379 
   2380 int portmod_port_phychain_cl72_set(int unit, int port, const phymod_phy_access_t* phy_access,
   2381                                          const int chain_length,
   2382                                          uint32_t cl72_en)
   2383 {
   2384     int rv = PHYMOD_E_UNAVAIL;
   2385     int phy_index;
   2386     int is_legacy_phy = 0;
   2387 
   2388     /* start from the most external phy. */
   2389     phy_index = chain_length - 1;
   2390 
   2391     /* Most EXT */
   2392     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2393         is_legacy_phy = 0;
   2394 
   2395         /* if it is external phy, check to see if it is legacy phy. */
   2396         if (phy_index > 0) {
   2397             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2398             if (rv != PHYMOD_E_NONE) return rv;
   2399         }
   2400 
   2401         if (is_legacy_phy) {
   2402             rv = portmod_port_legacy_cl72_set(unit, port, cl72_en);
   2403             return rv;
   2404         } else {
   2405             if (phy_access[phy_index].access.lane_mask) {
   2406                 rv = phymod_phy_cl72_set(&phy_access[phy_index], cl72_en);
   2407             } else {
   2408                 rv = PHYMOD_E_NONE;
   2409             }
   2410             return rv;
   2411         }
   2412         /*
   2413          * COVERITY
   2414          *
   2415          * This default is unreachable. It is kept intentionally as a defensive default for future
   2416          * development.
   2417          */
   2418         /* coverity[unreachable] */
   2419         phy_index--;
   2420     }
   2421     return(rv);
   2422 }
   2423 
   2424 int portmod_port_phychain_cl72_get(int unit, const phymod_phy_access_t* phy_access,
   2425                                          const int chain_length,
   2426                                          uint32_t *cl72_en)
   2427 {
   2428     int rv = PHYMOD_E_UNAVAIL;
   2429     int phy_index;
   2430     int is_legacy_phy = 0;
   2431     
   2432     /* start from the most external phy. */
   2433     phy_index = chain_length - 1;
   2434 
   2435     /* Most EXT */
   2436     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2437         if (phy_index) {
   2438             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2439             if (rv != PHYMOD_E_NONE) return rv;
   2440         } 
   2441         if (!is_legacy_phy) {
   2442             if(phy_access[phy_index].access.lane_mask){
   2443                 rv = phymod_phy_cl72_get(&phy_access[phy_index], cl72_en);
   2444             } else {
   2445                 rv = PHYMOD_E_NONE;
   2446             }
   2447             return rv;
   2448         }
   2449         phy_index--;
   2450     }
   2451     return(rv);
   2452 }
   2453 
   2454 int portmod_port_phychain_cl72_status_get(int unit, const phymod_phy_access_t* phy_access, 
   2455                                           const int chain_length,
   2456                                           phymod_cl72_status_t *status)
   2457 {
   2458     int rv = PHYMOD_E_UNAVAIL;
   2459     int phy_index;
   2460     int is_legacy_phy = 0;
   2461     
   2462     /* start from the most external phy. */
   2463     phy_index = chain_length - 1;
   2464 
   2465     /* Most EXT */
   2466     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2467         if (phy_index) {
   2468             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2469             if (rv != PHYMOD_E_NONE) return rv;
   2470         } 
   2471         if (!is_legacy_phy) {
   2472             rv = phymod_phy_cl72_status_get(&phy_access[phy_index], status);
   2473             return rv;
   2474         }
   2475         phy_index--;
   2476     }
   2477     return(rv);
   2478 }
   2479 
   2480 int portmod_port_phychain_autoneg_ability_set(int unit, int port, const phymod_phy_access_t* phy_access,
   2481                                               const int chain_length, uint32 flags,
   2482                                               const phymod_autoneg_ability_t* an_ability,
   2483                                               const portmod_port_ability_t * port_ability)
   2484 {
   2485     int rv = PHYMOD_E_UNAVAIL;
   2486     int phy_index;
   2487     int is_legacy_phy = 0;
   2488     phymod_operation_mode_t phy_op_mode = phymodOperationModeRetimer;
   2489 
   2490     rv = portmod_port_phychain_operation_mode_get(unit, port, phy_access, chain_length, &phy_op_mode);
   2491 
   2492     if ((flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) || ((phy_op_mode == phymodOperationModePassthru) &&
   2493         (rv == PHYMOD_E_NONE))) {
   2494         return phymod_phy_autoneg_ability_set(&phy_access[0], an_ability); 
   2495     }
   2496 
   2497     /* start from the most external phy. */
   2498     phy_index = chain_length - 1;
   2499     rv = PHYMOD_E_UNAVAIL;
   2500 
   2501     /* Most EXT */
   2502     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2503 
   2504         is_legacy_phy = 0;
   2505 
   2506         /* if it is external phy, check to see if it is legacy phy. */
   2507         if (phy_index > 0) {
   2508             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2509             if (rv != PHYMOD_E_NONE) return rv;
   2510         }
   2511 
   2512         if (is_legacy_phy) {
   2513             rv = portmod_port_legacy_advert_set(unit, port, port_ability);
   2514         } else {
   2515             if (phy_access[phy_index].access.lane_mask) {
   2516                 rv = phymod_phy_autoneg_ability_set(&phy_access[phy_index], an_ability);
   2517             } else {
   2518                 rv = PHYMOD_E_NONE;
   2519             }
   2520         }
   2521         phy_index--;
   2522     }
   2523     return(rv);
   2524 }
   2525 
   2526 int portmod_port_phychain_autoneg_ability_get(int unit, int port, const phymod_phy_access_t* phy_access,
   2527                                               const int chain_length, uint32 flags,
   2528                                               phymod_autoneg_ability_t* an_ability,
   2529                                               portmod_port_ability_t * port_ability)
   2530 {
   2531     int rv = PHYMOD_E_UNAVAIL;
   2532     int phy_index;
   2533     int is_legacy_phy = 0;
   2534     phymod_operation_mode_t phy_op_mode = phymodOperationModeRetimer;
   2535 
   2536     rv = portmod_port_phychain_operation_mode_get(unit, port, phy_access, chain_length, &phy_op_mode);
   2537     
   2538     /* When flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY returns 1,
   2539      * it means that the current function is called by a legacy external
   2540      * PHY API through the portmod callback function. In this case,
   2541      * the target to retrieve information is always the internal PHY.
   2542      */
   2543     if ((flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) || ((phy_op_mode == phymodOperationModePassthru) &&
   2544         (rv == PHYMOD_E_NONE))) {
   2545         rv = phymod_phy_autoneg_ability_get(&phy_access[0], an_ability);
   2546 
   2547         /* when there a legacy ext PHY attaching to a port, the caller of this function
   2548          * expects that the retrieved abilities are stored in port_ability.
   2549          */
   2550         portmod_common_phy_to_port_ability(an_ability, port_ability);
   2551         return(rv);
   2552     }
   2553 
   2554     /* start from the most external phy. */
   2555     phy_index = chain_length - 1;
   2556     rv = PHYMOD_E_UNAVAIL;
   2557 
   2558     /* Most EXT */
   2559     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2560 
   2561         is_legacy_phy = 0;
   2562 
   2563         /* if it is external phy, check to see if it is legacy phy. */
   2564         if (phy_index > 0) {
   2565             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2566             if (rv != PHYMOD_E_NONE) return rv;
   2567         }
   2568 
   2569         if (is_legacy_phy) {
   2570             rv = portmod_port_legacy_advert_get(unit, port, port_ability);
   2571         } else {
   2572             rv = phymod_phy_autoneg_ability_get(&phy_access[phy_index], an_ability);
   2573         }
   2574         phy_index--;
   2575     }
   2576     return(rv);
   2577 }
   2578 int portmod_port_phychain_local_ability_get(int unit, int port, const phymod_phy_access_t* phy_access,
   2579                                             const int chain_length,
   2580                                             portmod_port_ability_t* port_ability)
   2581 {
   2582     int rv = PHYMOD_E_UNAVAIL;
   2583     int phy_index;
   2584     int is_legacy_phy = 0;
   2585 
   2586     /* start from the most external phy. */
   2587     phy_index = chain_length - 1;
   2588 
   2589     /* Most EXT */
   2590     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2591         if (phy_index) {
   2592             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2593             if (rv != PHYMOD_E_NONE) return rv;
   2594             if (is_legacy_phy) {
   2595                 rv = portmod_port_legacy_ability_local_get(unit, port, port_ability);
   2596             } else {
   2597                 return rv;
   2598             }
   2599         } else {
   2600             return rv;
   2601         }
   2602         phy_index--;
   2603     }
   2604     return(rv);
   2605 }
   2606 int portmod_port_phychain_autoneg_restart_set(int unit, const phymod_phy_access_t* phy_access,
   2607                                                               const int chain_length)
   2608 {
   2609     int rv = PHYMOD_E_UNAVAIL;
   2610     int phy_index;
   2611     phymod_autoneg_control_t an;
   2612     int is_legacy_phy = 0;
   2613     
   2614     /* start from the most external phy. */
   2615     phy_index = chain_length - 1;
   2616 
   2617     /* Most EXT */
   2618     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2619         if (phy_index) {
   2620             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2621             if (rv != PHYMOD_E_NONE) return rv;
   2622         } 
   2623         if (!is_legacy_phy) {
   2624             phymod_autoneg_control_t_init(&an);
   2625             an.an_mode = phymod_AN_MODE_CL37_SGMII;
   2626             rv = phymod_phy_autoneg_restart_set(&phy_access[phy_index], &an);
   2627         }
   2628         phy_index--;
   2629     }
   2630     return(rv);
   2631 
   2632 }
   2633 
   2634 int portmod_port_phychain_autoneg_remote_ability_get(int unit, int port, const phymod_phy_access_t* phy_access,
   2635                                                      const int chain_length, uint32 flags,
   2636                                                      phymod_autoneg_ability_t* an_ability,
   2637                                                      portmod_port_ability_t * port_ability)
   2638 {
   2639     int rv = PHYMOD_E_UNAVAIL;
   2640     int phy_index;
   2641     int is_legacy_phy = 0;
   2642     phymod_operation_mode_t phy_op_mode = phymodOperationModeRetimer;
   2643 
   2644     rv = portmod_port_phychain_operation_mode_get(unit, port, phy_access, chain_length, &phy_op_mode);
   2645     
   2646     /* When flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY returns 1,
   2647      * it means that the current function is called by a legacy external
   2648      * PHY API through the portmod callback function. In this case,
   2649      * the target to retrieve information is always the internal PHY.
   2650      */
   2651     if ((flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) || ((phy_op_mode == phymodOperationModePassthru) &&
   2652         (rv == PHYMOD_E_NONE))) {
   2653         rv = phymod_phy_autoneg_remote_ability_get(&phy_access[0], an_ability);
   2654         /* when there a legacy ext PHY attaching to a port, the caller of this function
   2655          * expects that the retrieved abilities are stored in port_ability.
   2656          */
   2657         portmod_common_phy_to_port_ability(an_ability, port_ability);
   2658         return(rv);
   2659     }
   2660 
   2661     /* start from the most external phy. */
   2662     phy_index = chain_length - 1;
   2663     rv = PHYMOD_E_UNAVAIL;
   2664 
   2665     /* Most EXT */
   2666     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2667         is_legacy_phy = 0;
   2668 
   2669         /* if it is external phy, check to see if it is legacy phy. */
   2670         if (phy_index > 0) {
   2671             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2672             if (rv != PHYMOD_E_NONE) return rv;
   2673         }
   2674 
   2675         if (is_legacy_phy) {
   2676             rv = portmod_port_legacy_ability_remote_get(unit, port, port_ability);
   2677         } else {
   2678             rv = phymod_phy_autoneg_remote_ability_get(&phy_access[phy_index], an_ability);
   2679         }
   2680         phy_index--; 
   2681     }
   2682     return(rv);
   2683 }
   2684 
   2685 int portmod_port_phychain_autoneg_set(int unit, int port, const phymod_phy_access_t* phy_access,
   2686                                       const int chain_length, uint32 flags,
   2687                                       const phymod_autoneg_control_t *an_config)
   2688 {
   2689     int rv = PHYMOD_E_UNAVAIL;
   2690     int phy_index;
   2691     int is_legacy_phy = 0;
   2692     phymod_operation_mode_t phy_op_mode = phymodOperationModeRetimer;
   2693 
   2694     rv = portmod_port_phychain_operation_mode_get(unit, port, phy_access, chain_length, &phy_op_mode);
   2695 
   2696     if ((flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) || ((phy_op_mode == phymodOperationModePassthru) &&
   2697         (rv == PHYMOD_E_NONE))) {
   2698         return phymod_phy_autoneg_set(&phy_access[0], an_config); 
   2699     }
   2700 
   2701     /* start from the most external phy. */
   2702     phy_index = chain_length - 1;
   2703     rv = PHYMOD_E_UNAVAIL;
   2704 
   2705     /* Most EXT */
   2706     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2707 
   2708         is_legacy_phy = 0;
   2709 
   2710         /* if it is external phy, check to see if it is legacy phy. */
   2711         if (phy_index > 0) {
   2712             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2713             if (rv != PHYMOD_E_NONE) return rv;
   2714         }
   2715 
   2716         if (is_legacy_phy) {
   2717                 rv = portmod_port_legacy_an_set(unit, port, an_config);
   2718         } else {
   2719             if (phy_access[phy_index].access.lane_mask) {
   2720                 rv = phymod_phy_autoneg_set(&phy_access[phy_index], an_config);
   2721             } else {
   2722                 rv = PHYMOD_E_NONE;
   2723             }
   2724         }
   2725         phy_index--;
   2726     }
   2727     return(rv);
   2728 }
   2729 
   2730 int portmod_port_phychain_autoneg_get(int unit, int port, const phymod_phy_access_t* phy_access,
   2731                                       const int chain_length, uint32 flags,
   2732                                       phymod_autoneg_control_t *an_config,
   2733                                       uint32_t * an_done)
   2734 {
   2735     int rv = PHYMOD_E_UNAVAIL;
   2736     int phy_index;
   2737     int is_legacy_phy = 0;
   2738     phymod_operation_mode_t phy_op_mode = phymodOperationModeRetimer;
   2739 
   2740     rv = portmod_port_phychain_operation_mode_get(unit, port, phy_access, chain_length, &phy_op_mode);
   2741 
   2742     if ((flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY) || ((phy_op_mode == phymodOperationModePassthru) &&
   2743         (rv == PHYMOD_E_NONE))) {
   2744         return phymod_phy_autoneg_get(&phy_access[0], an_config, an_done); 
   2745     }
   2746 
   2747     /* start from the most external phy. */
   2748     phy_index = chain_length - 1;
   2749     rv = PHYMOD_E_UNAVAIL;
   2750 
   2751     /* Most EXT */
   2752     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2753         is_legacy_phy = 0;
   2754 
   2755         /* if it is external phy, check to see if it is legacy phy. */
   2756         if (phy_index > 0) {
   2757             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2758             if (rv != PHYMOD_E_NONE) return rv;
   2759         }
   2760 
   2761         if (is_legacy_phy) {
   2762             rv = portmod_port_legacy_an_get(unit, port, an_config, an_done);
   2763         } else {
   2764             if (phy_access[phy_index].access.lane_mask) {
   2765                 rv = phymod_phy_autoneg_get(&phy_access[phy_index], an_config, an_done);
   2766             } else {
   2767                 rv = PHYMOD_E_NONE;
   2768                 *an_done = 1;
   2769             }
   2770         }
   2771         phy_index--;
   2772     }
   2773     return(rv);
   2774 }
   2775 
   2776 int portmod_port_phychain_autoneg_status_get(int unit, int port, const phymod_phy_access_t* phy_access, 
   2777                                           const int chain_length,
   2778                                           phymod_autoneg_status_t *status)
   2779 {
   2780     int rv = PHYMOD_E_UNAVAIL;
   2781     int phy_index;
   2782     phymod_autoneg_control_t an;
   2783     uint32 an_done;
   2784     int is_legacy_phy = 0;
   2785     phymod_operation_mode_t phy_op_mode = phymodOperationModeRetimer;
   2786 
   2787     rv = portmod_port_phychain_operation_mode_get(unit, port, phy_access, chain_length, &phy_op_mode);
   2788     if ((phy_op_mode == phymodOperationModePassthru) && (rv == PHYMOD_E_NONE)) {
   2789         rv = phymod_phy_autoneg_get(&phy_access[0], &an, &an_done);
   2790         if (!rv) {
   2791             status->enabled   = an.enable;
   2792             status->locked    = an_done;
   2793         }
   2794         return rv;
   2795     }
   2796     
   2797     /* start from the most external phy. */
   2798     phy_index = chain_length - 1;
   2799     rv = PHYMOD_E_UNAVAIL;
   2800 
   2801     /* Most EXT */
   2802     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2803         is_legacy_phy = 0;
   2804 
   2805         /* if it is external phy, check to see if it is legacy phy. */
   2806         if (phy_index > 0) {
   2807             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2808             if (rv != PHYMOD_E_NONE) return rv;
   2809         }
   2810 
   2811         if (is_legacy_phy) {
   2812             rv = portmod_port_legacy_an_get(unit, port, &an, &an_done);
   2813         } else {
   2814             rv = phymod_phy_autoneg_get(&phy_access[phy_index], &an, &an_done);
   2815         }
   2816 
   2817         phy_index--;
   2818         if (!rv) {
   2819             status->enabled   = an.enable; 
   2820             status->locked    = an_done; 
   2821         }
   2822         return rv;
   2823     }
   2824     return(rv);
   2825 }
   2826 
   2827 int portmod_port_phychain_core_init(int unit, const phymod_core_access_t* core,
   2828                                     const int chain_length,
   2829                                     const phymod_core_init_config_t* init_config, 
   2830                                     const phymod_core_status_t* core_status)
   2831 {
   2832     int rv = PHYMOD_E_UNAVAIL;
   2833     int phy_index;
   2834     phymod_core_init_config_t core_config;
   2835     int lane;
   2836     phymod_core_access_t core_access;
   2837     phymod_firmware_load_method_t  fw_load_method;
   2838     int force_fw_load;
   2839     phymod_lane_map_t lane_map;
   2840     int is_legacy_phy = 0;
   2841  
   2842     /* start from the most external phy. */
   2843     phy_index = chain_length - 1;
   2844 
   2845     /* ALL PHYS */
   2846     while(((rv == PHYMOD_E_NONE) || (rv == PHYMOD_E_UNAVAIL)) && (phy_index >= 0)) {
   2847         if (phy_index) {
   2848             /* core init for the legacy phys are done as part of phy init */
   2849             rv = portmod_xphy_is_legacy_phy_get(unit, core[phy_index].access.addr, &is_legacy_phy);
   2850             if (rv != PHYMOD_E_NONE) return rv;
   2851         }
   2852 
   2853         if (!is_legacy_phy) {
   2854             sal_memcpy(&core_config, init_config,sizeof(phymod_core_init_config_t));
   2855             if(phy_index > 0) { /* external phy */
   2856 
   2857                 SOC_IF_ERROR_RETURN(portmod_xphy_core_access_get(unit, core[phy_index].access.addr, &core_access, &is_legacy_phy));
   2858                 SOC_IF_ERROR_RETURN(portmod_xphy_fw_load_method_get(unit, core[phy_index].access.addr, &fw_load_method));
   2859                 SOC_IF_ERROR_RETURN(portmod_xphy_force_fw_load_get(unit, core[phy_index].access.addr, &force_fw_load));
   2860                 SOC_IF_ERROR_RETURN(portmod_xphy_lane_map_get(unit, core[phy_index].access.addr, &lane_map));
   2861                 /* for external phys, FW load method is default to Internal
   2862                    unless it is force to NONE. */
   2863                 core_config.firmware_load_method = fw_load_method;
   2864                 core_config.firmware_loader = NULL;
   2865                 if (force_fw_load == phymodFirmwareLoadForce) {
   2866                     PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_SET(&core_config);
   2867                 }
   2868                 else if (force_fw_load == phymodFirmwareLoadAuto) {
   2869                     PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_SET(&core_config);
   2870                 }
   2871 
   2872 
   2873                 /* config "no swap" for external phys.set later using APIs*/
   2874                 for(lane=0 ; lane < lane_map.num_of_lanes; lane++) {
   2875                     core_config.lane_map.lane_map_rx[lane] = lane_map.lane_map_rx[lane];
   2876                     core_config.lane_map.lane_map_tx[lane] = lane_map.lane_map_tx[lane];
   2877                 }
   2878             }
   2879             rv = phymod_core_init(&core[phy_index], &core_config, core_status);
   2880         }
   2881         phy_index--;
   2882     }
   2883     return(rv);
   2884 }
   2885 
   2886 int portmod_port_phychain_pll_multiplier_get(int unit, const phymod_phy_access_t* phy_access,
   2887                                              const int chain_length,
   2888                                              uint32_t *core_vco_pll_multiplier)
   2889 {
   2890     int rv = PHYMOD_E_UNAVAIL;
   2891     int phy_index;
   2892     int is_legacy_phy = 0;
   2893     
   2894     /* start from the most external phy. */
   2895     phy_index = chain_length - 1;
   2896 
   2897     /* Most EXT */
   2898     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2899         if (phy_index) {
   2900             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2901             if (rv != PHYMOD_E_NONE) return rv;
   2902         }
   2903         if (!is_legacy_phy) {
   2904             rv = phymod_phy_pll_multiplier_get(&phy_access[phy_index], core_vco_pll_multiplier);
   2905         }
   2906         phy_index--;
   2907     }
   2908     return(rv);
   2909 }
   2910 
   2911 int portmod_port_phychain_phy_init(int unit, const phymod_phy_access_t* phy_access,
   2912                                    const int chain_length,
   2913                                    const phymod_phy_init_config_t* init_config)
   2914 {
   2915     int rv = PHYMOD_E_NONE;
   2916     int tx_rv = PHYMOD_E_NONE;
   2917     int phy_index;
   2918     phymod_phy_init_config_t local_init_config;
   2919     phymod_polarity_t polarity;
   2920     phymod_tx_t phymod_tx;
   2921     int i;
   2922     int is_legacy_phy = 0;
   2923 
   2924     sal_memcpy(&local_init_config, init_config, sizeof(phymod_phy_init_config_t));
   2925 
   2926     /* start from the most external phy. */
   2927     phy_index = chain_length - 1;
   2928 
   2929     /* ALL PHYS */
   2930     while(((rv == PHYMOD_E_NONE) || (rv == PHYMOD_E_UNAVAIL)) && (phy_index >= 0)) {
   2931         is_legacy_phy = 0;
   2932 
   2933         /* if it is external phy, check to see if it is legacy phy. */
   2934         if (phy_index > 0) {
   2935             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   2936             if (rv != PHYMOD_E_NONE) return rv;
   2937         }
   2938 
   2939         if (is_legacy_phy) {
   2940             phy_index--;
   2941             sal_memcpy(&local_init_config, init_config, sizeof(phymod_phy_init_config_t));
   2942             /* get default tx paramters for internal and intermediary phys. */
   2943             tx_rv = phymod_phy_media_type_tx_get(&phy_access[phy_index], phymodMediaTypeChipToChip, &phymod_tx);
   2944             /* if we can get the custom default tx paramter, use it.  Otherwise, use whatever it has in there. */
   2945             if( tx_rv == PHYMOD_E_NONE ) {
   2946                 for(i=0 ; i<PHYMOD_MAX_LANES_PER_CORE; i++) {
   2947                     local_init_config.tx[i].pre  = phymod_tx.pre  ;
   2948                     local_init_config.tx[i].main = phymod_tx.main ;
   2949                     local_init_config.tx[i].post = phymod_tx.post ;
   2950                     local_init_config.tx[i].post2= phymod_tx.post2;
   2951                     local_init_config.tx[i].post3= phymod_tx.post3;
   2952                     local_init_config.tx[i].amp  = phymod_tx.amp  ;
   2953                 }
   2954             }
   2955 
   2956         } else {
   2957             sal_memcpy(&local_init_config, init_config, sizeof(phymod_phy_init_config_t));
   2958 
   2959             if(phy_index != 0 ){
   2960                 phymod_polarity_t_init(&local_init_config.polarity);
   2961                 rv = portmod_xphy_polarity_get(unit, phy_access[phy_index].access.addr, &polarity);
   2962                 if (rv == PHYMOD_E_NONE) {
   2963                 sal_memcpy(&(local_init_config.polarity), &(polarity), sizeof(phymod_polarity_t));
   2964 
   2965                 /* overwrite tx params if set by config. phymod_phy_init only use tx, not ext_phy_tx */
   2966                 for(i=0 ; i<PHYMOD_MAX_LANES_PER_CORE; i++) {
   2967                     local_init_config.tx[i].pre  = init_config->ext_phy_tx[i].pre  ;
   2968                     local_init_config.tx[i].main = init_config->ext_phy_tx[i].main ;
   2969                     local_init_config.tx[i].post = init_config->ext_phy_tx[i].post ;
   2970                     local_init_config.tx[i].post2 = init_config->ext_phy_tx[i].post2 ;
   2971                     local_init_config.tx[i].post3 = init_config->ext_phy_tx[i].post3 ;
   2972                     local_init_config.tx[i].amp  = init_config->ext_phy_tx[i].amp  ;
   2973                 }
   2974                 } else return (rv);
   2975             }
   2976 
   2977             if(phy_access[phy_index].access.lane_mask){
   2978                 rv = phymod_phy_init(&phy_access[phy_index], &local_init_config);
   2979             }
   2980 
   2981             phy_index--;
   2982         }
   2983     } /* while */
   2984     return(rv);
   2985 }
   2986 int portmod_port_phychain_rx_pmd_locked_get(int unit, const phymod_phy_access_t* phy_access,
   2987                                          const int chain_length,
   2988                                          uint32_t *rx_pmd_locked)
   2989 {
   2990     int rv = PHYMOD_E_UNAVAIL;
   2991     int phy_index;
   2992     int is_legacy_phy = 0;
   2993     
   2994     /* start from the most external phy. */
   2995     phy_index = chain_length - 1;
   2996 
   2997     /* Most EXT */
   2998     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   2999         if (phy_index) {
   3000             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3001             if (rv != PHYMOD_E_NONE) return rv;
   3002         }
   3003         if (!is_legacy_phy) {
   3004             rv = phymod_phy_rx_pmd_locked_get(&phy_access[phy_index], rx_pmd_locked);
   3005         }
   3006         phy_index--;
   3007     }
   3008     return(rv);
   3009 }
   3010 
   3011 int portmod_port_phychain_link_status_get(int unit, int port, const phymod_phy_access_t* phy_access,
   3012                                          const int chain_length, uint32 flags,
   3013                                          uint32_t *link_status)
   3014 {
   3015     int rv = PHYMOD_E_UNAVAIL;
   3016     int phy_index;
   3017     uint32_t link_status_chain = 0;
   3018     int psc_repeater_mode = 0;
   3019     int is_legacy_phy = 0;
   3020     
   3021     /* start from the most external phy. */
   3022     phy_index = chain_length - 1;
   3023     psc_repeater_mode = PHYMOD_INTF_CONFIG_PHY_PSC_REPEATER_MODE_GET(&phy_access[chain_length - 1]) ;
   3024 
   3025     /* Check if the phy access is targetted for internal phy only */
   3026     if (flags == PORTMOD_INIT_F_INTERNAL_SERDES_ONLY){ 
   3027         return  phymod_phy_link_status_get(&phy_access[0], link_status);
   3028     }
   3029     /*if external PHY is working on psc_repeater  Most EXT & SerDes else Most EXT */
   3030     while(((PHYMOD_E_UNAVAIL== rv) || psc_repeater_mode) && (phy_index >= 0)) {
   3031         is_legacy_phy = 0;
   3032 
   3033         /* if it is external phy, check to see if it is legacy phy. */
   3034         if (phy_index > 0) {
   3035             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3036             if (rv != PHYMOD_E_NONE) return rv;
   3037         }
   3038 
   3039         if (is_legacy_phy) {
   3040                 rv = portmod_port_legacy_phy_link_get(unit, port, link_status);
   3041         } else {
   3042             if (phy_access[phy_index].access.lane_mask) {
   3043                 rv = phymod_phy_link_status_get(&phy_access[phy_index], &link_status_chain);
   3044                 if (psc_repeater_mode) {
   3045                     if (phy_index == chain_length -1) {
   3046                                 *link_status = link_status_chain ;
   3047                     } else {
   3048                         *link_status &= link_status_chain;
   3049                     }
   3050                 } else {
   3051                     *link_status = link_status_chain;
   3052                 }
   3053             } else {
   3054                 rv = PHYMOD_E_NONE;
   3055                 *link_status = 1;
   3056             }
   3057         }
   3058         phy_index--;
   3059     }
   3060     return(rv);
   3061 }
   3062 
   3063 int portmod_port_phychain_pcs_userspeed_set(int unit, const phymod_phy_access_t* phy_access,
   3064                                             const int chain_length,
   3065                                             const phymod_pcs_userspeed_config_t* config)
   3066 {
   3067     int rv = PHYMOD_E_UNAVAIL;
   3068     int phy_index;
   3069     int is_legacy_phy = 0;
   3070 
   3071     /* start from the most external phy. */
   3072     phy_index = chain_length - 1;
   3073 
   3074     /* Most EXT */
   3075     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3076         if (phy_index) {
   3077             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3078             if (rv != PHYMOD_E_NONE) return rv;
   3079         }
   3080         if (!is_legacy_phy) {
   3081             rv = phymod_phy_pcs_userspeed_set(&phy_access[phy_index], config);
   3082         }
   3083         phy_index--;
   3084     }
   3085     return(rv);
   3086 }
   3087 
   3088 int portmod_port_phychain_pcs_userspeed_get(int unit, const phymod_phy_access_t* phy_access,
   3089                                             const int chain_length,
   3090                                             phymod_pcs_userspeed_config_t* config)
   3091 {
   3092     int rv = PHYMOD_E_UNAVAIL;
   3093     int phy_index;
   3094     int is_legacy_phy = 0;
   3095 
   3096     /* start from the most external phy. */
   3097     phy_index = chain_length - 1;
   3098 
   3099     /* Most EXT */
   3100     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3101         if (phy_index) {
   3102             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3103             if (rv != PHYMOD_E_NONE) return rv;
   3104         }if (!is_legacy_phy) {
   3105             rv = phymod_phy_pcs_userspeed_get(&phy_access[phy_index], config);
   3106         }
   3107         phy_index--;
   3108     }
   3109     return(rv);
   3110 }
   3111 
   3112 int portmod_port_phychain_reg_write(int unit, int port, const phymod_phy_access_t* phy_access,
   3113                                     const int chain_length,
   3114                                     int lane,
   3115                                     uint32_t flags,
   3116                                     uint32_t reg_addr,
   3117                                     uint32_t reg_val) 
   3118 {
   3119     int rv = PHYMOD_E_UNAVAIL;
   3120     int phy_index;
   3121     uint8 data8;
   3122     int is_legacy_phy = 0;
   3123 
   3124     if (flags & SOC_PHY_INTERNAL) { 
   3125         phy_index = 0;
   3126     } else {
   3127         /* start from the most external phy. */
   3128         phy_index = chain_length - 1;
   3129     }
   3130 
   3131     /* Most EXT if internal is not specified */
   3132     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3133         is_legacy_phy = 0;
   3134 
   3135         /* if it is external phy, check to see if it is legacy phy. */
   3136         if (phy_index > 0) {
   3137             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3138             if (rv != PHYMOD_E_NONE) return rv;
   3139         }
   3140 
   3141         if (is_legacy_phy) {
   3142             rv = portmod_port_legacy_reg_write(unit, port, flags, reg_addr, reg_val);
   3143         } else {
   3144             if (flags & BCM_PORT_PHY_I2C_DATA8) {
   3145                 data8 = reg_val & 0xFF;
   3146                 rv = phymod_phy_i2c_write( &phy_access[phy_index], 0,
   3147                                           BCM_PORT_PHY_I2C_DEVAD(reg_addr),
   3148                                           BCM_PORT_PHY_I2C_REGAD(reg_addr),
   3149                                           1,&data8 );
   3150             } else {
   3151                 if (lane >= 0) {
   3152                     reg_addr |= PHYMOD_REG_ACC_AER_IBLK_FORCE_LANE;
   3153                     reg_addr &= ~(0x7 << PHYMOD_REG_ACCESS_FLAGS_SHIFT);
   3154                     reg_addr |= ((lane & 0x7) << PHYMOD_REG_ACCESS_FLAGS_SHIFT);
   3155                 }
   3156                 rv = phymod_phy_reg_write(&phy_access[phy_index], reg_addr, reg_val);
   3157             }
   3158         }
   3159         phy_index--;
   3160     }
   3161     return(rv);
   3162 }
   3163 
   3164 int portmod_port_phychain_reg_read(int unit, int port, const phymod_phy_access_t* phy_access,
   3165                                    const int chain_length,
   3166                                    int lane,
   3167                                    uint32_t flags,
   3168                                    uint32_t reg_addr,
   3169                                    uint32_t *reg_val)
   3170 {
   3171     int rv = PHYMOD_E_UNAVAIL;
   3172     int phy_index;
   3173     uint8 data8;
   3174     int is_legacy_phy = 0;
   3175 
   3176     if (flags & SOC_PHY_INTERNAL) { 
   3177         phy_index = 0;
   3178     } else {
   3179         /* start from the most external phy. */
   3180         phy_index = chain_length - 1;
   3181     }
   3182 
   3183     /* Most EXT if internal is not specified */
   3184     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3185         is_legacy_phy = 0;
   3186 
   3187         /* if it is external phy, check to see if it is legacy phy. */
   3188         if (phy_index > 0) {
   3189             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3190             if (rv != PHYMOD_E_NONE) return rv;
   3191         }
   3192 
   3193         if (is_legacy_phy) {
   3194             rv = portmod_port_legacy_reg_read(unit, port, flags, reg_addr, reg_val);
   3195         } else {
   3196             if (flags & BCM_PORT_PHY_I2C_DATA8) {
   3197                 rv = phymod_phy_i2c_read( &phy_access[phy_index], 0,
   3198                                           BCM_PORT_PHY_I2C_DEVAD(reg_addr),
   3199                                           BCM_PORT_PHY_I2C_REGAD(reg_addr),
   3200                                           1, &data8);
   3201                 *reg_val = data8;
   3202             } else {
   3203                 if (lane >= 0) {
   3204                     reg_addr |= PHYMOD_REG_ACC_AER_IBLK_FORCE_LANE;
   3205                     reg_addr &= ~(0x7 << PHYMOD_REG_ACCESS_FLAGS_SHIFT);
   3206                     reg_addr |= ((lane & 0x7) << PHYMOD_REG_ACCESS_FLAGS_SHIFT);
   3207                 }
   3208                 rv = phymod_phy_reg_read(&phy_access[phy_index], reg_addr, reg_val);
   3209             }
   3210         }
   3211         phy_index--;
   3212     }
   3213     return(rv);
   3214 }
   3215 
   3216 int portmod_port_phychain_rx_slicer_position_set(int unit, const phymod_phy_access_t* phy_access,
   3217                                                  const int chain_length,
   3218                                                  uint32_t flags,
   3219                                                  const phymod_slicer_position_t* position)
   3220 {
   3221     int rv = PHYMOD_E_UNAVAIL;
   3222     int phy_index;
   3223     int is_legacy_phy = 0;
   3224 
   3225     /* start from the most external phy. */
   3226     phy_index = chain_length - 1;
   3227 
   3228     /* Most EXT */
   3229     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3230         if (phy_index) {
   3231             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3232             if (rv != PHYMOD_E_NONE) return rv;
   3233         }
   3234         if (!is_legacy_phy) {
   3235             rv = phymod_phy_rx_slicer_position_set(&phy_access[phy_index], flags, position);
   3236         }
   3237         phy_index--;
   3238     }
   3239     return(rv);
   3240 }
   3241 
   3242 int portmod_port_phychain_rx_slicer_position_get(int unit, const phymod_phy_access_t* phy_access,
   3243                                                  const int chain_length,
   3244                                                  uint32_t flags,
   3245                                                  phymod_slicer_position_t* position)
   3246 {
   3247     int rv = PHYMOD_E_UNAVAIL;
   3248     int phy_index;
   3249     int is_legacy_phy = 0;
   3250 
   3251     /* start from the most external phy. */
   3252     phy_index = chain_length - 1;           
   3253                                             
   3254     /* Most EXT */               
   3255     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3256         if (phy_index) {
   3257             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3258             if (rv != PHYMOD_E_NONE) return rv;           
   3259         }
   3260         if (!is_legacy_phy) {
   3261             rv = phymod_phy_rx_slicer_position_get(&phy_access[phy_index], flags, position);
   3262         }
   3263         phy_index--;
   3264     }
   3265     return(rv);
   3266 }
   3267 
   3268 int portmod_port_phychain_rx_slicer_position_max_get(int unit, const phymod_phy_access_t* phy_access,
   3269                                                      const int chain_length,
   3270                                                      uint32_t flags,
   3271                                                      phymod_slicer_position_t* position_min,
   3272                                                      phymod_slicer_position_t* position_max)
   3273 { 
   3274     int rv = PHYMOD_E_UNAVAIL;
   3275     int phy_index;
   3276     int is_legacy_phy = 0;
   3277 
   3278     /* start from the most external phy. */
   3279     phy_index = chain_length - 1;
   3280  
   3281     /* Most EXT */    
   3282     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3283         if (phy_index) {
   3284             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3285             if (rv != PHYMOD_E_NONE) return rv;
   3286         }
   3287         if (!is_legacy_phy) {
   3288             rv = phymod_phy_rx_slicer_position_max_get(&phy_access[phy_index], flags, position_min, position_max);
   3289         }
   3290         phy_index--;
   3291     }
   3292     return(rv);
   3293 }
   3294 
   3295 int portmod_port_phychain_prbs_config_set(int unit, const phymod_phy_access_t* phy_access,
   3296                                           const int chain_length,
   3297                                           uint32_t flags,
   3298                                           const phymod_prbs_t* prbs)
   3299 {
   3300     int rv = PHYMOD_E_UNAVAIL;
   3301     int phy_index;
   3302     int is_legacy_phy = 0;
   3303 
   3304     /* start from the most external phy. */
   3305     phy_index = chain_length - 1;
   3306 
   3307     /* Most EXT */
   3308     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3309         if (phy_index) {
   3310             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3311             if (rv != PHYMOD_E_NONE) return rv;
   3312         }
   3313         if (!is_legacy_phy) {
   3314             rv = phymod_phy_prbs_config_set(&phy_access[phy_index], flags, prbs);
   3315         }
   3316         phy_index--;
   3317     }
   3318     return(rv);
   3319 }
   3320 
   3321 int portmod_port_phychain_prbs_config_get(int unit, const phymod_phy_access_t* phy_access,
   3322                                           const int chain_length,
   3323                                           uint32_t flags,
   3324                                           phymod_prbs_t* prbs)
   3325 {
   3326     int rv = PHYMOD_E_UNAVAIL;
   3327     int phy_index;
   3328     int is_legacy_phy = 0;
   3329 
   3330     /* start from the most external phy. */
   3331     phy_index = chain_length - 1;
   3332  
   3333     /* Most EXT */
   3334     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3335         if (phy_index) {
   3336             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3337             if (rv != PHYMOD_E_NONE) return rv;
   3338         } 
   3339         if (!is_legacy_phy) {
   3340             rv = phymod_phy_prbs_config_get(&phy_access[phy_index], flags, prbs);
   3341         }
   3342         phy_index--;
   3343     }
   3344     return(rv);
   3345 }
   3346 
   3347 int portmod_port_phychain_prbs_enable_set(int unit, const phymod_phy_access_t* phy_access,
   3348                                           const int chain_length,
   3349                                           uint32_t flags,
   3350                                           uint32_t enable)                                                   
   3351 {
   3352     int rv = PHYMOD_E_UNAVAIL;
   3353     int phy_index;
   3354     int is_legacy_phy = 0;
   3355 
   3356     /* start from the most external phy. */
   3357     phy_index = chain_length - 1;
   3358 
   3359     /* Most EXT */
   3360     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3361         if (phy_index) {
   3362             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3363             if (rv != PHYMOD_E_NONE) return rv;
   3364         } 
   3365         if (!is_legacy_phy) {
   3366             rv = phymod_phy_prbs_enable_set(&phy_access[phy_index], flags, enable);
   3367         }
   3368         phy_index--;
   3369     }
   3370     return(rv);
   3371 }
   3372 
   3373 int portmod_port_phychain_prbs_enable_get(int unit, const phymod_phy_access_t* phy_access,
   3374                                           const int chain_length,
   3375                                           uint32_t flags,
   3376                                           uint32_t *enable)                                                   
   3377 {
   3378     int rv = PHYMOD_E_UNAVAIL;
   3379     int phy_index;
   3380     int is_legacy_phy = 0;
   3381 
   3382     /* start from the most external phy. */
   3383     phy_index = chain_length - 1;
   3384  
   3385     /* Most EXT */
   3386     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3387         if (phy_index) {
   3388             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3389             if (rv != PHYMOD_E_NONE) return rv;
   3390         } 
   3391         if (!is_legacy_phy) {
   3392             rv = phymod_phy_prbs_enable_get(&phy_access[phy_index], flags, enable);
   3393         }
   3394         phy_index--;
   3395     }
   3396     return(rv);
   3397 }
   3398 
   3399 int portmod_port_phychain_prbs_status_get(int unit, const phymod_phy_access_t* phy_access,
   3400                                           const int chain_length,
   3401                                           uint32_t flags,
   3402                                           phymod_prbs_status_t *prbs_status)
   3403 {
   3404     int rv = PHYMOD_E_UNAVAIL;
   3405     int phy_index;
   3406     int is_legacy_phy = 0;
   3407 
   3408     /* start from the most external phy. */
   3409     phy_index = chain_length - 1;
   3410 
   3411     /* Most EXT */
   3412     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3413         if (phy_index) {
   3414             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3415             if (rv != PHYMOD_E_NONE) return rv;
   3416         } 
   3417         if (!is_legacy_phy) {
   3418             rv = phymod_phy_prbs_status_get(&phy_access[phy_index], flags, prbs_status);
   3419         }
   3420         phy_index--;
   3421     }
   3422     return(rv);
   3423 }
   3424 
   3425 
   3426 int portmod_port_phychain_pattern_config_set(int unit, const phymod_phy_access_t* phy_access,
   3427                                              const int chain_length,
   3428                                              const phymod_pattern_t* pattern)
   3429 {
   3430     int rv = PHYMOD_E_UNAVAIL;
   3431     int phy_index;
   3432     int is_legacy_phy = 0;
   3433 
   3434     /* start from the most external phy. */
   3435     phy_index = chain_length - 1;
   3436 
   3437     /* Most EXT */
   3438     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3439         if (phy_index) {
   3440             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3441             if (rv != PHYMOD_E_NONE) return rv;
   3442         } 
   3443         if (!is_legacy_phy) {
   3444             rv = phymod_phy_pattern_config_set(&phy_access[phy_index], pattern);
   3445         }
   3446         phy_index--;
   3447     }
   3448     return(rv);
   3449 }
   3450 
   3451 int portmod_port_phychain_pattern_config_get(int unit, const phymod_phy_access_t* phy_access,
   3452                                              const int chain_length,
   3453                                              phymod_pattern_t* pattern)
   3454 {
   3455     int rv = PHYMOD_E_UNAVAIL;
   3456     int phy_index;
   3457     int is_legacy_phy = 0;
   3458 
   3459     /* start from the most external phy. */
   3460     phy_index = chain_length - 1;
   3461  
   3462     /* Most EXT */
   3463     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3464         if (phy_index) {
   3465             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3466             if (rv != PHYMOD_E_NONE) return rv;
   3467         } 
   3468         if (!is_legacy_phy) {
   3469             rv = phymod_phy_pattern_config_get(&phy_access[phy_index], pattern);
   3470         }
   3471         phy_index--;
   3472     }
   3473     return(rv);
   3474 }
   3475 
   3476 int portmod_port_phychain_pattern_enable_set(int unit, const phymod_phy_access_t* phy_access,
   3477                                              const int chain_length,
   3478                                              uint32_t enable,
   3479                                              phymod_pattern_t* pattern)                                                   
   3480 {
   3481     int rv = PHYMOD_E_UNAVAIL;
   3482     int phy_index;
   3483     int is_legacy_phy = 0;
   3484 
   3485     /* start from the most external phy. */
   3486     phy_index = chain_length - 1;
   3487 
   3488     /* Most EXT */
   3489     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3490         if (phy_index) {
   3491             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3492             if (rv != PHYMOD_E_NONE) return rv;
   3493         } 
   3494         if (!is_legacy_phy) {
   3495             rv = phymod_phy_pattern_enable_set(&phy_access[phy_index], enable, pattern);
   3496         }
   3497         phy_index--;
   3498     }
   3499     return(rv);
   3500 }
   3501 
   3502 int portmod_port_phychain_pattern_enable_get(int unit, const phymod_phy_access_t* phy_access,
   3503                                              const int chain_length,
   3504                                              uint32_t *enable)                                                   
   3505 {
   3506     int rv = PHYMOD_E_UNAVAIL;
   3507     int phy_index;
   3508     int is_legacy_phy = 0;
   3509 
   3510     /* start from the most external phy. */
   3511     phy_index = chain_length - 1;
   3512  
   3513     /* Most EXT */
   3514     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3515         if (phy_index) {
   3516             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3517             if (rv != PHYMOD_E_NONE) return rv;
   3518         } 
   3519         if (!is_legacy_phy) {
   3520             rv = phymod_phy_pattern_enable_get(&phy_access[phy_index], enable);
   3521         }
   3522         phy_index--;
   3523     }
   3524     return(rv);
   3525 }
   3526 
   3527 int portmod_port_phychain_core_diagnostics_get(int unit, const phymod_core_access_t* core,
   3528                                                const int chain_length,
   3529                                                phymod_core_diagnostics_t* diag) 
   3530 {
   3531     int rv = PHYMOD_E_UNAVAIL;
   3532     int phy_index;
   3533     int is_legacy_phy = 0;
   3534 
   3535     PHYMOD_NULL_CHECK(core);
   3536 
   3537     /* Most EXT first. */
   3538     phy_index = chain_length - 1;
   3539 
   3540     /* Most EXT */
   3541     while( (PHYMOD_E_UNAVAIL == rv) && (phy_index >= 0)) {
   3542         if (phy_index) {
   3543             rv = portmod_xphy_is_legacy_phy_get(unit, core[phy_index].access.addr, &is_legacy_phy);
   3544             if (rv != PHYMOD_E_NONE) return rv;
   3545         } 
   3546         if (!is_legacy_phy) {
   3547             rv = phymod_core_diagnostics_get(&core[phy_index], diag);
   3548         }
   3549         phy_index--;
   3550     }
   3551 
   3552     return(rv);
   3553 }
   3554 
   3555 int portmod_port_phychain_phy_diagnostics_get(int unit, const phymod_phy_access_t* phy_access,
   3556                                               const int chain_length,
   3557                                               phymod_phy_diagnostics_t *diag)
   3558 {
   3559     int rv = PHYMOD_E_UNAVAIL;
   3560     int phy_index;
   3561     int is_legacy_phy = 0;
   3562 
   3563     /* start from the most external phy. */
   3564     phy_index = chain_length - 1;
   3565 
   3566     /* Most EXT */
   3567     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3568         if (phy_index) {
   3569             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3570             if (rv != PHYMOD_E_NONE) return rv;
   3571         } 
   3572         if (!is_legacy_phy) {
   3573             rv = phymod_phy_diagnostics_get(&phy_access[phy_index], diag);
   3574         }
   3575         phy_index--;
   3576     }
   3577     return(rv);
   3578 }
   3579 
   3580 int portmod_port_phychain_pmd_info_dump(int unit, const phymod_phy_access_t* phy_access,
   3581                                         const int chain_length,
   3582                                         char *type)
   3583 {
   3584     int rv = PHYMOD_E_UNAVAIL;
   3585     int phy_index;
   3586     int is_legacy_phy = 0;
   3587 
   3588     /* start from the most external phy. */
   3589     phy_index = chain_length - 1;
   3590 
   3591     /* Most EXT */
   3592     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3593         if (phy_index) {
   3594             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3595             if (rv != PHYMOD_E_NONE) return rv;
   3596         } 
   3597         if (!is_legacy_phy) {
   3598             if(phy_access[phy_index].access.lane_mask){
   3599                 rv = phymod_phy_pmd_info_dump(&phy_access[phy_index], type);
   3600             } else {
   3601                 rv = PHYMOD_E_NONE;
   3602             }
   3603         }
   3604         phy_index--;
   3605     }
   3606     return(rv);
   3607 }
   3608 
   3609 int portmod_port_phychain_pcs_info_dump(int unit, const phymod_phy_access_t* phy_access,
   3610                                         const int chain_length,
   3611                                         char *type)
   3612 {
   3613     int rv = PHYMOD_E_UNAVAIL;
   3614     int phy_index;
   3615     int is_legacy_phy = 0;
   3616 
   3617     /* start from the most external phy. */
   3618     phy_index = chain_length - 1;
   3619 
   3620     /* Most EXT */
   3621     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3622         if (phy_index) {
   3623             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3624             if (rv != PHYMOD_E_NONE) return rv;
   3625         } 
   3626         if (!is_legacy_phy) {
   3627             if(phy_access[phy_index].access.lane_mask) {
   3628                 rv = phymod_phy_pcs_info_dump(&phy_access[phy_index], type);
   3629             } else {
   3630                 rv = PHYMOD_E_NONE;
   3631             }
   3632         }
   3633         phy_index--;
   3634     }
   3635     return(rv);
   3636 }
   3637 
   3638 #ifdef _OLD_EYE_
   3639 int portmod_port_phychain_meas_lowber_eye(int unit, const phymod_phy_access_t* phy_access,
   3640                                           const int chain_length,
   3641                                           phymod_phy_eyescan_options_t eyescan_options,
   3642                                           uint32_t *buffer)
   3643 {
   3644     int rv = PHYMOD_E_UNAVAIL;
   3645     int phy_index;
   3646     int is_legacy_phy = 0;
   3647 
   3648     /* start from the most external phy. */
   3649     phy_index = chain_length - 1;
   3650 
   3651     /* Most EXT */
   3652     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3653         if (phy_index) {
   3654             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3655             if (rv != PHYMOD_E_NONE) return rv;
   3656         } 
   3657         if (!is_legacy_phy) {
   3658             rv = phymod_phy_meas_lowber_eye(&phy_access[phy_index], eyescan_options, buffer);
   3659         }
   3660         phy_index--;
   3661     }
   3662     return(rv);
   3663 }
   3664 int portmod_port_phychain_display_lowber_eye(int unit, const phymod_phy_access_t* phy_access,
   3665                                              const int chain_length,
   3666                                              phymod_phy_eyescan_options_t eyescan_options,
   3667                                              uint32_t *buffer)
   3668 {
   3669     int rv = PHYMOD_E_UNAVAIL;
   3670     int phy_index;
   3671     int is_legacy_phy = 0;
   3672 
   3673     /* start from the most external phy. */
   3674     phy_index = chain_length - 1;
   3675 
   3676     /* Most EXT */
   3677     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3678         if (phy_index) {
   3679             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3680             if (rv != PHYMOD_E_NONE) return rv;
   3681         } 
   3682         if (!is_legacy_phy) {
   3683             rv = phymod_phy_display_lowber_eye(&phy_access[phy_index], eyescan_options, buffer);
   3684         }
   3685         phy_index--;
   3686     }
   3687     return(rv);
   3688 }
   3689 
   3690 
   3691 int portmod_port_phychain_pmd_ber_end_cmd(int unit, const phymod_phy_access_t* phy_access,
   3692                                           const int chain_length,
   3693                                           uint8_t supp_info,
   3694                                           uint32_t timeout_ms)
   3695 {
   3696     int rv = PHYMOD_E_UNAVAIL;
   3697     int phy_index;
   3698     int is_legacy_phy = 0;
   3699 
   3700     /* start from the most external phy. */
   3701     phy_index = chain_length - 1;
   3702 
   3703     /* Most EXT */
   3704     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3705         if (phy_index) {
   3706             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3707             if (rv != PHYMOD_E_NONE) return rv;
   3708         } 
   3709         if (!is_legacy_phy) {
   3710             rv = phymod_phy_pmd_ber_end_cmd(&phy_access[phy_index], supp_info, timeout_ms); 
   3711         }
   3712         phy_index--;
   3713     }
   3714     return(rv);
   3715 }
   3716 
   3717 int portmod_port_phychain_meas_eye_scan_start(int unit, const phymod_phy_access_t* phy_access,
   3718                                               const int chain_length,
   3719                                               uint8_t direction)
   3720 {
   3721     int rv = PHYMOD_E_UNAVAIL;
   3722     int phy_index;
   3723     int is_legacy_phy = 0;
   3724 
   3725     /* start from the most external phy. */
   3726     phy_index = chain_length - 1;
   3727 
   3728     /* Most EXT */
   3729     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3730         if (phy_index) {
   3731             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3732             if (rv != PHYMOD_E_NONE) return rv;
   3733         } 
   3734         if (!is_legacy_phy) {
   3735             rv = phymod_phy_meas_eye_scan_start(&phy_access[phy_index], direction); 
   3736         }
   3737         phy_index--;
   3738     }
   3739     return(rv);
   3740 }
   3741 
   3742 int portmod_port_phychain_meas_eye_scan_done(int unit, const phymod_phy_access_t* phy_access,
   3743                                              const int chain_length)
   3744 {
   3745     int rv = PHYMOD_E_UNAVAIL;
   3746     int phy_index;
   3747     int is_legacy_phy = 0;
   3748 
   3749     /* start from the most external phy. */
   3750     phy_index = chain_length - 1;
   3751 
   3752     /* Most EXT */
   3753     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3754         if (phy_index) {
   3755             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3756             if (rv != PHYMOD_E_NONE) return rv;
   3757         } 
   3758         if (!is_legacy_phy) {
   3759             rv = phymod_phy_meas_eye_scan_done(&phy_access[phy_index]);
   3760         }
   3761         phy_index--;
   3762     }
   3763     return(rv);
   3764 }
   3765 
   3766 int portmod_port_phychain_read_eye_scan_stripe(int unit, const phymod_phy_access_t* phy_access,
   3767                                                const int chain_length,
   3768                                                uint32_t *buffer,
   3769                                                uint16_t *status)
   3770 {
   3771     int rv = PHYMOD_E_UNAVAIL;
   3772     int phy_index;
   3773     int is_legacy_phy = 0;
   3774 
   3775     /* start from the most external phy. */
   3776     phy_index = chain_length - 1;
   3777 
   3778     /* Most EXT */
   3779     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3780         if (phy_index) {
   3781             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3782             if (rv != PHYMOD_E_NONE) return rv;
   3783         } 
   3784         if (!is_legacy_phy) {
   3785             rv = phymod_phy_read_eye_scan_stripe(&phy_access[phy_index], buffer, status);
   3786         }
   3787         phy_index--;
   3788     }
   3789     return(rv);
   3790 }
   3791 
   3792 int portmod_port_phychain_display_eye_scan_header(int unit, const phymod_phy_access_t* phy_access,
   3793                                                   const int chain_length,
   3794                                                   uint8_t index)
   3795 {
   3796     int rv = PHYMOD_E_UNAVAIL;
   3797     int phy_index;
   3798     int is_legacy_phy = 0;
   3799 
   3800     /* start from the most external phy. */
   3801     phy_index = chain_length - 1;
   3802 
   3803     /* Most EXT */
   3804     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3805         if (phy_index) {
   3806             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3807             if (rv != PHYMOD_E_NONE) return rv;
   3808         } 
   3809         if (!is_legacy_phy) {
   3810             rv = phymod_phy_display_eye_scan_header(&phy_access[phy_index], index);
   3811         }
   3812         phy_index--;
   3813     }
   3814     return(rv);
   3815 }
   3816 
   3817 int portmod_port_phychain_display_eye_scan_footer(int unit, const phymod_phy_access_t* phy_access,
   3818                                                   const int chain_length,
   3819                                                   uint8_t index)
   3820 {
   3821     int rv = PHYMOD_E_UNAVAIL;
   3822     int phy_index;
   3823     int is_legacy_phy = 0;
   3824 
   3825     /* start from the most external phy. */
   3826     phy_index = chain_length - 1;
   3827 
   3828     /* Most EXT */
   3829     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3830         if (phy_index) {
   3831             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3832             if (rv != PHYMOD_E_NONE) return rv;
   3833         } 
   3834         if (!is_legacy_phy) {
   3835             rv = phymod_phy_display_eye_scan_footer(&phy_access[phy_index], index);
   3836         }
   3837         phy_index--;
   3838     }
   3839     return(rv);
   3840 }
   3841 
   3842 int portmod_port_phychain_display_eye_scan_stripe(int unit, const phymod_phy_access_t* phy_access,
   3843                                                   const int chain_length,
   3844                                                   uint8_t index,
   3845                                                   uint32_t *buffer)
   3846 {
   3847     int rv = PHYMOD_E_UNAVAIL;
   3848     int phy_index;
   3849     int is_legacy_phy = 0;
   3850 
   3851     /* start from the most external phy. */
   3852     phy_index = chain_length - 1;
   3853 
   3854     /* Most EXT */
   3855     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3856         if (phy_index) {
   3857             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3858             if (rv != PHYMOD_E_NONE) return rv;
   3859         } 
   3860         if (!is_legacy_phy) {
   3861             rv = phymod_phy_display_eye_scan_stripe(&phy_access[phy_index], index,buffer);
   3862         }
   3863         phy_index--;
   3864     }
   3865     return(rv);
   3866 }
   3867 
   3868 int portmod_port_phychain_eye_scan_debug_info_dump(int unit, const phymod_phy_access_t* phy_access,
   3869                                                    const int chain_length)
   3870 {
   3871     int rv = PHYMOD_E_UNAVAIL;
   3872     int phy_index;
   3873     int is_legacy_phy = 0;
   3874     
   3875     /* start from the most external phy. */
   3876     phy_index = chain_length - 1;
   3877 
   3878     /* Most EXT */
   3879     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3880         if (phy_index) {
   3881             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3882             if (rv != PHYMOD_E_NONE) return rv;
   3883         } 
   3884         if (!is_legacy_phy) {
   3885             rv = phymod_phy_eye_scan_debug_info_dump(&phy_access[phy_index]);
   3886         }
   3887         phy_index--;
   3888     }
   3889     return(rv);
   3890 }
   3891 #else
   3892 /* add phy_eyescan_run here */
   3893 
   3894 #endif /* _OLD_EYE_ */
   3895 
   3896 int portmod_port_phychain_timesync_tx_info_get(int unit, int port, const phymod_phy_access_t* phy_access,
   3897                                               const int chain_length,
   3898                                               phymod_ts_fifo_status_t* ts_tx_info)
   3899 {
   3900     int rv = PHYMOD_E_UNAVAIL;
   3901     int phy_index;
   3902     int is_legacy_phy = 0;
   3903 
   3904     /* start from the most external phy. */
   3905     phy_index = chain_length - 1;
   3906 
   3907     /* Most EXT */
   3908     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3909 
   3910         is_legacy_phy = 0;
   3911 
   3912         /* if it is external phy, check to see if it is legacy phy. */
   3913         if (phy_index > 0) {
   3914             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3915             if (rv != PHYMOD_E_NONE) return rv;
   3916         }
   3917 
   3918         if (!is_legacy_phy) {
   3919             rv = phymod_timesync_tx_info_get(&phy_access[phy_index], ts_tx_info);
   3920         }
   3921 
   3922         phy_index--;
   3923     }
   3924 
   3925     return(rv);
   3926 }
   3927 
   3928 int portmod_port_phychain_timesync_config_set(int unit, int port, const phymod_phy_access_t* phy_access, 
   3929                                               const int chain_length, 
   3930                                               const portmod_phy_timesync_config_t* config)
   3931 {
   3932     int rv = PHYMOD_E_UNAVAIL;
   3933     int phy_index;
   3934     int is_legacy_phy = 0;
   3935     uint32_t enable = 0;
   3936 
   3937     /* start from the most external phy. */
   3938     phy_index = chain_length - 1;
   3939 
   3940     /* Most EXT */
   3941     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3942         is_legacy_phy = 0;
   3943 
   3944         /* if it is external phy, check to see if it is legacy phy. */
   3945         if (phy_index > 0) {
   3946             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3947             if (rv != PHYMOD_E_NONE) return rv;
   3948         }
   3949 
   3950         if (is_legacy_phy) {
   3951             rv = portmod_port_legacy_timesync_config_set(unit, port, config);
   3952         } else {
   3953             if (phy_access[phy_index].access.lane_mask) {
   3954                 enable = (config->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) ? 1 : 0;
   3955                 rv = phymod_timesync_enable_set(&phy_access[phy_index], 0, enable);
   3956             } else {
   3957                 rv = PHYMOD_E_NONE;
   3958             }
   3959         }
   3960         phy_index--;
   3961     }
   3962     return(rv);
   3963 }
   3964 
   3965 int portmod_port_phychain_timesync_config_get(int unit, int port, const phymod_phy_access_t* phy_access, 
   3966                                               const int chain_length, 
   3967                                               portmod_phy_timesync_config_t* config)
   3968 {
   3969     int rv = PHYMOD_E_UNAVAIL;
   3970     int phy_index;
   3971     int is_legacy_phy = 0;
   3972     uint32_t enable = 0;
   3973 
   3974     /* start from the most external phy. */
   3975     phy_index = chain_length - 1;
   3976 
   3977     /* Most EXT */
   3978     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   3979 
   3980         is_legacy_phy = 0;
   3981 
   3982         /* if it is external phy, check to see if it is legacy phy. */
   3983         if (phy_index > 0) {
   3984             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   3985             if (rv != PHYMOD_E_NONE) return rv;
   3986         }
   3987 
   3988         if (is_legacy_phy) {
   3989             rv = portmod_port_legacy_timesync_config_get(unit, port, config);
   3990         } else {
   3991             if (phy_access[phy_index].access.lane_mask) {
   3992                 rv = phymod_timesync_enable_get(&phy_access[phy_index], 0, &enable);
   3993                 config->flags |= enable ? SOC_PORT_PHY_TIMESYNC_ENABLE : 0;
   3994             } else {
   3995                 rv = PHYMOD_E_NONE;
   3996             }
   3997         }
   3998         phy_index--;
   3999     }
   4000     
   4001     return(rv);
   4002 }
   4003 
   4004 
   4005 int portmod_port_phychain_timesync_enable_set(int unit, const phymod_phy_access_t* phy_access, 
   4006                                               const int chain_length, uint32 enable)
   4007 {
   4008     int rv = PHYMOD_E_UNAVAIL;
   4009     int phy_index;
   4010     int is_legacy_phy = 0;
   4011 
   4012     /* start from the most external phy. */
   4013     phy_index = chain_length - 1;
   4014 
   4015     /* Most EXT */
   4016     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4017         if (phy_index) {
   4018             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4019             if (rv != PHYMOD_E_NONE) return rv;
   4020         } 
   4021         if (!is_legacy_phy) {
   4022             rv = phymod_timesync_enable_set(&phy_access[phy_index], 0, enable);
   4023         }
   4024         phy_index--;
   4025     }
   4026     return(rv);
   4027 }
   4028 
   4029 int portmod_port_phychain_timesync_enable_get(int unit, const phymod_phy_access_t* phy_access, 
   4030                                               const int chain_length, uint32* enable)
   4031 {
   4032     int rv = PHYMOD_E_UNAVAIL;
   4033     int phy_index;
   4034     int is_legacy_phy = 0;
   4035 
   4036     /* start from the most external phy. */
   4037     phy_index = chain_length - 1;
   4038 
   4039     /* Most EXT */
   4040     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4041         if (phy_index) {
   4042             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4043             if (rv != PHYMOD_E_NONE) return rv;
   4044         } 
   4045         if (!is_legacy_phy) {
   4046             rv = phymod_timesync_enable_get(&phy_access[phy_index], 0, enable);
   4047         }
   4048         phy_index--;
   4049     }
   4050     return(rv);
   4051 }
   4052 
   4053 int portmod_port_phychain_timesync_nco_addend_set(int unit, const phymod_phy_access_t* phy_access, 
   4054                                                   const int chain_length, uint32 freq_step)
   4055 {
   4056     int rv = PHYMOD_E_UNAVAIL;
   4057     int phy_index;
   4058     int is_legacy_phy = 0;
   4059 
   4060     /* start from the most external phy. */
   4061     phy_index = chain_length - 1;
   4062 
   4063     /* Most EXT */
   4064     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4065         if (phy_index) {
   4066             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4067             if (rv != PHYMOD_E_NONE) return rv;
   4068         } 
   4069         if (!is_legacy_phy) {
   4070             rv = phymod_timesync_nco_addend_set(&phy_access[phy_index], freq_step);
   4071         }
   4072         phy_index--;
   4073     }
   4074     return(rv);
   4075 }
   4076 
   4077 int portmod_port_phychain_timesync_nco_addend_get(int unit, const phymod_phy_access_t* phy_access, 
   4078                                                   const int chain_length, 
   4079                                                   uint32* freq_step)
   4080     {
   4081     int rv = PHYMOD_E_UNAVAIL;
   4082     int phy_index;                   
   4083     int is_legacy_phy = 0;
   4084 
   4085     /* start from the most external phy. */
   4086     phy_index = chain_length - 1;
   4087                                                       
   4088     /* Most EXT */
   4089     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4090         if (phy_index) {
   4091             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4092             if (rv != PHYMOD_E_NONE) return rv;
   4093         } 
   4094         if (!is_legacy_phy) {
   4095             rv = phymod_timesync_nco_addend_get(&phy_access[phy_index], freq_step);
   4096         }
   4097         phy_index--;
   4098     }                                             
   4099     return(rv);
   4100 }
   4101 
   4102 int portmod_port_phychain_timesync_framesync_mode_set(int unit, const phymod_phy_access_t* phy_access, 
   4103                                                       const int chain_length, 
   4104                                                       const portmod_timesync_framesync_t* framesync)
   4105 {
   4106     int rv = PHYMOD_E_UNAVAIL;
   4107     int phy_index;                   
   4108     int is_legacy_phy = 0;
   4109 
   4110     phymod_timesync_framesync_t phymod_framesync;
   4111 
   4112     /* start from the most external phy. */
   4113     phy_index = chain_length - 1;
   4114     sal_memcpy(&phymod_framesync, framesync, sizeof(phymod_timesync_framesync_t));
   4115     /* Most EXT */
   4116     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4117         if (phy_index) {
   4118             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4119             if (rv != PHYMOD_E_NONE) return rv;
   4120         } 
   4121         if (!is_legacy_phy) {
   4122             rv = phymod_timesync_framesync_mode_set(&phy_access[phy_index], &phymod_framesync);
   4123         }
   4124         phy_index--;
   4125     }                                             
   4126     return(rv);
   4127 }
   4128 
   4129 int portmod_port_phychain_timesync_framesync_mode_get(int unit, const phymod_phy_access_t* phy_access, 
   4130                                                       const int chain_length, 
   4131                                                       phymod_timesync_framesync_t* framesync)
   4132 {
   4133     int rv = PHYMOD_E_UNAVAIL;
   4134     int phy_index;
   4135     int is_legacy_phy = 0;
   4136 
   4137     phymod_timesync_framesync_t phymod_framesync;
   4138                   
   4139     sal_memset(&phymod_framesync, 0, sizeof(phymod_timesync_framesync_t));
   4140     /* start from the most external phy. */
   4141     phy_index = chain_length - 1;
   4142                                                       
   4143     /* Most EXT */               
   4144     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4145         if (phy_index) {
   4146             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4147             if (rv != PHYMOD_E_NONE) return rv;                 
   4148         } 
   4149         if (!is_legacy_phy) {
   4150             rv = phymod_timesync_framesync_mode_get(&phy_access[phy_index], &phymod_framesync);
   4151         }
   4152         phy_index--;
   4153     }
   4154     sal_memcpy(framesync,&phymod_framesync,  sizeof(phymod_timesync_framesync_t));
   4155                                                       
   4156     return(rv);
   4157 }
   4158 
   4159 int portmod_port_phychain_timesync_local_time_set(int unit, const phymod_phy_access_t* phy_access, 
   4160                                                   const int chain_length, 
   4161                                                   const uint64 local_time)
   4162 {
   4163     int rv = PHYMOD_E_UNAVAIL;
   4164     int phy_index;
   4165     int is_legacy_phy = 0;
   4166                   
   4167     /* start from the most external phy. */
   4168     phy_index = chain_length - 1;
   4169                                                       
   4170     /* Most EXT */               
   4171     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4172         if (phy_index) {
   4173             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4174             if (rv != PHYMOD_E_NONE) return rv;                 
   4175         } 
   4176         if (!is_legacy_phy) {
   4177             rv = phymod_timesync_local_time_set(&phy_access[phy_index], local_time);
   4178         }
   4179         phy_index--;
   4180     }
   4181     return(rv);
   4182 }
   4183 
   4184 int portmod_port_phychain_timesync_local_time_get(int unit, const phymod_phy_access_t* phy_access, 
   4185                                                   const int chain_length, 
   4186                                                   uint64* local_time)
   4187 {
   4188     int rv = PHYMOD_E_UNAVAIL;
   4189     int phy_index;
   4190     int is_legacy_phy = 0;
   4191 
   4192     /* start from the most external phy. */
   4193     phy_index = chain_length - 1;
   4194                                                        
   4195     /* Most EXT */               
   4196     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4197         if (phy_index) {
   4198             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4199             if (rv != PHYMOD_E_NONE) return rv;                 
   4200         } 
   4201         if (!is_legacy_phy) {
   4202             rv = phymod_timesync_local_time_get(&phy_access[phy_index], local_time);
   4203         }
   4204         phy_index--;
   4205     }
   4206     return(rv);
   4207 }
   4208 
   4209 int portmod_port_phychain_timesync_load_ctrl_set(int unit, const phymod_phy_access_t* phy_access, 
   4210                                                  const int chain_length, 
   4211                                                  uint32 load_once, 
   4212                                                  uint32 load_always)
   4213 {
   4214     int rv = PHYMOD_E_UNAVAIL;
   4215     int phy_index;
   4216     int is_legacy_phy = 0;
   4217 
   4218     /* start from the most external phy. */
   4219     phy_index = chain_length - 1;
   4220                                                        
   4221     /* Most EXT */               
   4222     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4223         if (phy_index) {
   4224             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4225             if (rv != PHYMOD_E_NONE) return rv;                 
   4226         } 
   4227         if (!is_legacy_phy) {
   4228             rv = phymod_timesync_load_ctrl_set(&phy_access[phy_index], load_once,
   4229                                                          load_always);
   4230         }
   4231         phy_index--;
   4232     }
   4233     return(rv);
   4234 }
   4235 
   4236 int portmod_port_phychain_timesync_load_ctrl_get(int unit, const phymod_phy_access_t* phy_access, 
   4237                                                  const int chain_length, 
   4238                                                  uint32* load_once, 
   4239                                                  uint32* load_always)
   4240 {
   4241     int rv = PHYMOD_E_UNAVAIL;
   4242     int phy_index;
   4243     int is_legacy_phy = 0;
   4244 
   4245     /* start from the most external phy. */
   4246     phy_index = chain_length - 1;
   4247                                                        
   4248     /* Most EXT */
   4249     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4250         if (phy_index) {
   4251             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4252             if (rv != PHYMOD_E_NONE) return rv;
   4253         } 
   4254         if (!is_legacy_phy) {
   4255             rv = phymod_timesync_load_ctrl_get(&phy_access[phy_index], load_once,
   4256                                                          load_always);
   4257         }
   4258         phy_index--;
   4259     }
   4260     return(rv);
   4261 }
   4262 
   4263 int portmod_port_phychain_timesync_tx_timestamp_offset_set(int unit, const phymod_phy_access_t* phy_access, 
   4264                                                            const int chain_length, 
   4265                                                            uint32 ts_offset)
   4266 {
   4267     int rv = PHYMOD_E_UNAVAIL;
   4268     int phy_index;
   4269     int is_legacy_phy = 0;
   4270 
   4271     /* start from the most external phy. */
   4272     phy_index = chain_length - 1;
   4273 
   4274     /* Most EXT */
   4275     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4276         if (phy_index) {
   4277             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4278             if (rv != PHYMOD_E_NONE) return rv;
   4279         } 
   4280         if (!is_legacy_phy) {
   4281             rv = phymod_timesync_tx_timestamp_offset_set(&phy_access[phy_index],ts_offset);
   4282         }
   4283         phy_index--;
   4284     }
   4285     return(rv);
   4286 }
   4287 
   4288 int portmod_port_phychain_timesync_tx_timestamp_offset_get(int unit, const phymod_phy_access_t* phy_access, 
   4289                                                            const int chain_length, 
   4290                                                            uint32* ts_offset)
   4291 {
   4292     int rv = PHYMOD_E_UNAVAIL;
   4293     int phy_index;
   4294     int is_legacy_phy = 0;                  
   4295 
   4296     /* start from the most external phy. */
   4297     phy_index = chain_length - 1;
   4298                 
   4299     /* Most EXT */               
   4300     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4301         if (phy_index) {
   4302             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4303             if (rv != PHYMOD_E_NONE) return rv;                          
   4304         } 
   4305         if (!is_legacy_phy) {
   4306             rv = phymod_timesync_tx_timestamp_offset_get(&phy_access[phy_index],ts_offset);
   4307         }
   4308         phy_index--;                     
   4309     }
   4310     return(rv);
   4311 }
   4312 
   4313 int portmod_port_phychain_timesync_rx_timestamp_offset_set(int unit, const phymod_phy_access_t* phy_access, 
   4314                                                            const int chain_length, 
   4315                                                            uint32 ts_offset)
   4316 {
   4317     int rv = PHYMOD_E_UNAVAIL;
   4318     int phy_index;
   4319     int is_legacy_phy = 0;                  
   4320 
   4321     /* start from the most external phy. */
   4322     phy_index = chain_length - 1;
   4323                 
   4324     /* Most EXT */               
   4325     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4326         if (phy_index) {
   4327             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4328             if (rv != PHYMOD_E_NONE) return rv;                          
   4329         } 
   4330         if (!is_legacy_phy) {
   4331             rv = phymod_timesync_rx_timestamp_offset_set(&phy_access[phy_index],ts_offset);
   4332         }
   4333         phy_index--;                             
   4334     }
   4335     return(rv);
   4336 }
   4337 
   4338 int portmod_port_phychain_timesync_rx_timestamp_offset_get(int unit, const phymod_phy_access_t* phy_access, 
   4339                                                            const int chain_length, 
   4340                                                            uint32* ts_offset)
   4341 {
   4342     int rv = PHYMOD_E_UNAVAIL;
   4343     int phy_index;
   4344     int is_legacy_phy = 0;                  
   4345 
   4346     /* start from the most external phy. */
   4347     phy_index = chain_length - 1;
   4348                 
   4349     /* Most EXT */               
   4350     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4351         if (phy_index) {
   4352             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4353             if (rv != PHYMOD_E_NONE) return rv;                          
   4354         } 
   4355         if (!is_legacy_phy) {
   4356             rv = phymod_timesync_rx_timestamp_offset_get(&phy_access[phy_index],ts_offset);
   4357         }
   4358         phy_index--;                             
   4359     }
   4360     return(rv);
   4361 }
   4362 
   4363 int portmod_port_phychain_phy_intr_enable_set(int unit, const phymod_phy_access_t* phy_access, 
   4364                                        const int chain_length, 
   4365                                        uint32_t enable)
   4366 {
   4367     int rv = PHYMOD_E_UNAVAIL;
   4368     int phy_index;
   4369     int is_legacy_phy = 0;                  
   4370 
   4371     /* start from the most external phy. */
   4372     phy_index = chain_length - 1;
   4373                 
   4374     /* Most EXT */               
   4375     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4376         if (phy_index) {
   4377             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4378             if (rv != PHYMOD_E_NONE) return rv;                          
   4379         } 
   4380         if (!is_legacy_phy){
   4381             rv = phymod_phy_intr_enable_set(&phy_access[phy_index], enable);
   4382         }
   4383         phy_index--;                             
   4384     }
   4385     return(rv);
   4386 }
   4387 
   4388 int portmod_port_phychain_phy_intr_enable_get(int unit, const phymod_phy_access_t* phy_access, 
   4389                                               const int chain_length, 
   4390                                               uint32_t* enable)
   4391 {
   4392     int rv = PHYMOD_E_UNAVAIL;
   4393     int phy_index;
   4394     int is_legacy_phy = 0;
   4395 
   4396     /* start from the most external phy. */
   4397     phy_index = chain_length - 1;
   4398 
   4399     /* Most EXT */
   4400     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4401         if (phy_index) {
   4402             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4403             if (rv != PHYMOD_E_NONE) return rv;
   4404         } 
   4405         if (!is_legacy_phy) {
   4406             rv = phymod_phy_intr_enable_get(&phy_access[phy_index],enable);
   4407         }
   4408         phy_index--;
   4409     }
   4410     return(rv);
   4411 }
   4412 
   4413 int portmod_port_phychain_phy_intr_status_get(int unit, const phymod_phy_access_t* phy_access,
   4414                                               const int chain_length,
   4415                                               uint32_t* enable)
   4416 {
   4417     int rv = PHYMOD_E_UNAVAIL;
   4418     int phy_index;
   4419     int is_legacy_phy = 0;
   4420 
   4421     /* start from the most external phy. */
   4422     phy_index = chain_length - 1;
   4423 
   4424     /* Most EXT */
   4425     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4426         if (phy_index) {
   4427             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4428             if (rv != PHYMOD_E_NONE) return rv;
   4429         } 
   4430         if (!is_legacy_phy) {
   4431             rv = phymod_phy_intr_status_get(&phy_access[phy_index],enable);
   4432         }
   4433         phy_index--;
   4434     }
   4435     return(rv);
   4436 }
   4437 
   4438 int portmod_port_phychain_phy_intr_status_clear(int unit, const phymod_phy_access_t* phy_access,
   4439                                               const int chain_length)
   4440 {
   4441     int rv = PHYMOD_E_UNAVAIL;
   4442     int phy_index;
   4443     uint32_t enable=0;
   4444     int is_legacy_phy = 0;
   4445 
   4446     /* start from the most external phy. */
   4447     phy_index = chain_length - 1;
   4448 
   4449     /* Most EXT */
   4450     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4451         if (phy_index) {
   4452             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4453             if (rv != PHYMOD_E_NONE) return rv;
   4454         } 
   4455         if (!is_legacy_phy) {
   4456             rv = phymod_phy_intr_status_get(&phy_access[phy_index], &enable);
   4457             if (rv) return (rv);
   4458 
   4459             rv = phymod_phy_intr_status_clear(&phy_access[phy_index], enable);
   4460         }
   4461         phy_index--;
   4462     }
   4463     return(rv);
   4464 }
   4465 
   4466 int portmod_port_phychain_phy_timesync_do_sync(int unit, const phymod_phy_access_t* phy_access,
   4467                                                const int chain_length )
   4468 {
   4469     int rv = PHYMOD_E_UNAVAIL;
   4470     int phy_index;
   4471     int is_legacy_phy = 0;
   4472     
   4473 
   4474     /* start from the most external phy. */
   4475     phy_index = chain_length - 1;
   4476 
   4477     /* Most EXT */
   4478     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4479         if (phy_index) {
   4480             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4481             if (rv != PHYMOD_E_NONE) return rv;
   4482         } 
   4483         if (!is_legacy_phy) {
   4484              rv = phymod_timesync_do_sync(&phy_access[phy_index]); 
   4485         }
   4486         phy_index--;
   4487     }
   4488     return(rv);
   4489 }
   4490 
   4491 int portmod_port_phychain_timesync_capture_timestamp_get(int unit, const phymod_phy_access_t* phy_access, 
   4492                                                          const int chain_length, uint64* cap_ts)
   4493 {
   4494     int rv = PHYMOD_E_UNAVAIL;
   4495     int phy_index;
   4496     int is_legacy_phy = 0;
   4497 
   4498     /* start from the most external phy. */
   4499     phy_index = chain_length - 1;
   4500 
   4501     /* Most EXT */
   4502     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4503         if (phy_index) {
   4504             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4505             if (rv != PHYMOD_E_NONE) return rv;
   4506         } 
   4507         if (!is_legacy_phy) {
   4508             rv = phymod_timesync_capture_timestamp_get(&phy_access[phy_index],cap_ts);
   4509         }
   4510         phy_index--;
   4511     }
   4512     return(rv);
   4513 }
   4514 
   4515 int portmod_port_phychain_timesync_heartbeat_timestamp_get(int unit, const phymod_phy_access_t* phy_access, 
   4516                                                            const int chain_length, uint64* hb_ts)
   4517 {
   4518     int rv = PHYMOD_E_UNAVAIL;
   4519     int phy_index;
   4520     int is_legacy_phy = 0;
   4521 
   4522     /* start from the most external phy. */
   4523     phy_index = chain_length - 1;
   4524 
   4525     /* Most EXT */
   4526     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4527         if (phy_index) {
   4528             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4529             if (rv != PHYMOD_E_NONE) return rv;
   4530         } 
   4531         if (!is_legacy_phy) {
   4532             rv = phymod_timesync_heartbeat_timestamp_get(&phy_access[phy_index],hb_ts);
   4533         }
   4534         phy_index--;
   4535     }
   4536     return(rv);
   4537 }
   4538 int portmod_port_phychain_edc_config_set(int unit, const phymod_phy_access_t* phy_access,
   4539                                          const int chain_length,
   4540                                          const phymod_edc_config_t* config)
   4541 {
   4542     int rv = PHYMOD_E_UNAVAIL;
   4543     int phy_index;
   4544     int is_legacy_phy = 0;
   4545 
   4546     phymod_edc_config_t phymod_config;
   4547 
   4548     /* start from the most external phy. */
   4549     phy_index = chain_length - 1;
   4550 
   4551     sal_memcpy(&phymod_config, config,  sizeof(phymod_edc_config_t));
   4552     /* Most EXT */
   4553     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4554         if (phy_index) {
   4555             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4556             if (rv != PHYMOD_E_NONE) return rv;
   4557         } 
   4558         if (!is_legacy_phy) {
   4559             rv = phymod_edc_config_set(&phy_access[phy_index],&phymod_config);
   4560         }
   4561         phy_index--;
   4562     }
   4563     return(rv);
   4564 }
   4565 
   4566 int portmod_port_phychain_edc_config_get(int unit, const phymod_phy_access_t* phy_access,
   4567                                          const int chain_length,
   4568                                          phymod_edc_config_t* config)
   4569 {
   4570     int rv = PHYMOD_E_UNAVAIL;
   4571     int phy_index;
   4572     int is_legacy_phy = 0;
   4573     phymod_edc_config_t phymod_config;
   4574 
   4575     /* start from the most external phy. */
   4576     phy_index = chain_length - 1;
   4577 
   4578     sal_memset(&phymod_config,0,sizeof(phymod_edc_config_t));
   4579 
   4580     /* Most EXT */
   4581     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4582         if (phy_index) {
   4583             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4584             if (rv != PHYMOD_E_NONE) return rv;
   4585         } 
   4586         if (!is_legacy_phy) {
   4587             rv = phymod_edc_config_get(&phy_access[phy_index],&phymod_config);
   4588         }
   4589         phy_index--;
   4590     }
   4591     sal_memcpy(config,&phymod_config,  sizeof(phymod_edc_config_t));
   4592     return(rv);
   4593 }
   4594 
   4595 int portmod_port_phychain_failover_mode_get(int unit, const phymod_phy_access_t *phy_access, 
   4596                                   int chain_length, phymod_failover_mode_t *failover)
   4597 {
   4598     int rv = PHYMOD_E_UNAVAIL;
   4599     int phy_index;
   4600     int is_legacy_phy = 0;
   4601 
   4602     /* start from the most external phy. */
   4603     phy_index = chain_length - 1;
   4604 
   4605     /* Most EXT */
   4606     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4607         if (phy_index) {
   4608             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4609             if (rv != PHYMOD_E_NONE) return rv;
   4610         }
   4611         if (!is_legacy_phy) {
   4612             rv = phymod_failover_mode_get(&phy_access[phy_index], failover);
   4613         }
   4614         phy_index--;
   4615     }
   4616 
   4617     return(rv);
   4618 }
   4619 
   4620 int portmod_port_phychain_failover_mode_set(int unit, const phymod_phy_access_t *phy_access,
   4621                                   int chain_length, phymod_failover_mode_t failover)
   4622 {
   4623     int rv = PHYMOD_E_UNAVAIL;
   4624     int phy_index;
   4625     int is_legacy_phy = 0;
   4626 
   4627     /* start from the most external phy. */
   4628     phy_index = chain_length - 1;
   4629 
   4630     /* Most EXT */
   4631     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4632         if (phy_index) {
   4633             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4634             if (rv != PHYMOD_E_NONE) return rv;
   4635         }
   4636         if (!is_legacy_phy) {
   4637             rv = phymod_failover_mode_set(&phy_access[phy_index], failover);
   4638         }
   4639         phy_index--;
   4640     }
   4641 
   4642     return(rv);
   4643 }
   4644 
   4645 int portmod_port_phychain_phy_link_up_event(int unit, int port, const phymod_phy_access_t* phy_access,
   4646                                             const int chain_length)
   4647 {
   4648     int rv = PHYMOD_E_UNAVAIL;
   4649     int phy_index;
   4650     int is_legacy_phy = 0;
   4651 
   4652     /* start from the most external phy. */
   4653     phy_index = chain_length - 1;
   4654 
   4655     /* Most EXT */
   4656     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4657         if (phy_index) {
   4658             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4659             if (rv != PHYMOD_E_NONE) return rv;
   4660             if (is_legacy_phy) {
   4661                 rv = portmod_port_legacy_phy_link_up_event(unit, port);
   4662             } else {
   4663                 rv = PHYMOD_E_NONE;
   4664             }
   4665         } else {
   4666             rv = PHYMOD_E_NONE;
   4667         }
   4668         phy_index--;
   4669     }
   4670     return(rv);
   4671 }
   4672 
   4673 int portmod_port_phychain_phy_link_down_event(int unit, int port, const phymod_phy_access_t* phy_access,
   4674                                             const int chain_length)
   4675 {
   4676     int rv = PHYMOD_E_UNAVAIL;
   4677     int phy_index;
   4678     int is_legacy_phy = 0;
   4679 
   4680     /* start from the most external phy. */
   4681     phy_index = chain_length - 1;
   4682 
   4683     /* Most EXT */
   4684     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   4685         if (phy_index) {
   4686             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   4687             if (rv != PHYMOD_E_NONE) return rv;
   4688             if (is_legacy_phy) {
   4689                 rv = portmod_port_legacy_phy_link_down_event(unit, port);
   4690             } else {
   4691                 rv = PHYMOD_E_NONE;
   4692             }
   4693         } else {
   4694             rv = PHYMOD_E_NONE;
   4695         }
   4696         phy_index--;
   4697     }
   4698     return(rv);
   4699 }
   4700 
   4701 /*
   4702  * common routines between pm4x10 and pm4x25 
   4703  */
   4704 
   4705 int portmod_phy_port_diag_ctrl(int unit, soc_port_t port, phymod_phy_access_t *phy_access, 
   4706                       int nof_phys, uint32 inst, int op_type, int op_cmd, const void *arg) 
   4707 {
   4708     phymod_tx_t  ln_txparam[PHYMOD_MAX_LANES_PER_CORE];
   4709     uint32 lane_map = phy_access[0].access.lane_mask; 
   4710     int i;
   4711 
   4712     for (i = 0; i < PHYMOD_MAX_LANES_PER_CORE; i++) {
   4713         SOC_IF_ERROR_RETURN(phymod_tx_t_init(&ln_txparam[i]));
   4714     }
   4715     
   4716     switch(op_cmd) {
   4717         case PHY_DIAG_CTRL_DSC:
   4718             LOG_INFO(BSL_LS_SOC_PHY,
   4719                      (BSL_META_U(unit,
   4720                                  "portmod_phy_port_diag_ctrl: "
   4721                                  "u=%d p=%d PHY_DIAG_CTRL_DSC 0x%x\n"),
   4722                       unit, port, PHY_DIAG_CTRL_DSC));
   4723 
   4724             SOC_IF_ERROR_RETURN
   4725                 (portmod_port_phychain_pmd_info_dump(unit, phy_access, nof_phys,
   4726                                                  (void*)arg));
   4727 
   4728             break;
   4729 
   4730         case PHY_DIAG_CTRL_PCS:
   4731             LOG_INFO(BSL_LS_SOC_PHY,
   4732                      (BSL_META_U(unit,
   4733                                  "portmod_phy_port_diag_ctrl: "
   4734                                  "u=%d p=%d PHY_DIAG_CTRL_PCS 0x%x\n"),
   4735                       unit, port, PHY_DIAG_CTRL_PCS));
   4736 
   4737             SOC_IF_ERROR_RETURN
   4738                 (portmod_port_phychain_pcs_info_dump(unit, phy_access, nof_phys,
   4739                                                     (void*)arg));
   4740             break;
   4741 
   4742         case PHY_DIAG_CTRL_LINKMON_MODE:
   4743             LOG_INFO(BSL_LS_SOC_PHY,
   4744                      (BSL_META_U(unit,
   4745                                  "portmod_phy_port_diag_ctrl: "
   4746                                  "u=%d p=%d PHY_DIAG_CTRL_LINKMON_MODE  0x%x\n"),
   4747                       unit, port, PHY_DIAG_CTRL_LINKMON_MODE));
   4748 
   4749             if (phy_access[0].access.lane_mask) {
   4750                 SOC_IF_ERROR_RETURN
   4751                     (portmod_pm_phy_link_mon_enable_set(phy_access, nof_phys, PTR_TO_INT(arg)));
   4752             }
   4753             break;
   4754 
   4755         case PHY_DIAG_CTRL_LINKMON_STATUS:
   4756             LOG_INFO(BSL_LS_SOC_PHY,
   4757                      (BSL_META_U(unit,
   4758                                  "portmod_phy_port_diag_ctrl: "
   4759                                  "u=%d p=%d PHY_DIAG_CTRL_LINKMON_STATUS 0x%x\n"),
   4760                       unit, port, PHY_DIAG_CTRL_LINKMON_STATUS));
   4761 
   4762             if (phy_access[0].access.lane_mask) {
   4763                 SOC_IF_ERROR_RETURN
   4764                     (portmod_pm_phy_link_mon_status_get(phy_access, nof_phys));
   4765             }
   4766             break;
   4767        case PHY_DIAG_CTRL_BER_PROJ:
   4768             LOG_INFO(BSL_LS_SOC_PHY,
   4769                      (BSL_META_U(unit,
   4770                                  "portmod_phy_port_diag_ctrl: "
   4771                                  "u=%d p=%d PHY_DIAG_CTRL_BER_PROJ 0x%x\n"),
   4772                       unit, port, PHY_DIAG_CTRL_BER_PROJ));
   4773 
   4774             if (phy_access[0].access.lane_mask) {
   4775                 SOC_IF_ERROR_RETURN
   4776                     (portmod_pm_phy_ber_proj(phy_access, (soc_port_phy_ber_proj_params_t*)arg));
   4777             }
   4778             break;
   4779        case PHY_DIAG_CTRL_RSFEC_SYMB_ERR:
   4780             LOG_INFO(BSL_LS_SOC_PHY,
   4781                      (BSL_META_U(unit,
   4782                                  "portmod_phy_port_diag_ctrl: "
   4783                                  "u=%d p=%d PHY_DIAG_CTRL_RSFEC_SYMB_ERR 0x%x\n"),
   4784                       unit, port, PHY_DIAG_CTRL_RSFEC_SYMB_ERR));
   4785 
   4786             if (phy_access[0].access.lane_mask) {
   4787                 SOC_IF_ERROR_RETURN
   4788                     (portmod_pm_phy_rsfec_symb_err_get(phy_access,
   4789                                       (soc_port_phy_rsfec_symb_errcnt_t*)arg));
   4790             }
   4791             break;
   4792        default:
   4793             if (op_type == PHY_DIAG_CTRL_SET) {
   4794                 LOG_INFO(BSL_LS_SOC_PHY,
   4795                          (BSL_META_U(unit,
   4796                                      "portmod_phy_port_diag_ctrl: "
   4797                                      "u=%d p=%d PHY_DIAG_CTRL_SET 0x%x\n"),
   4798                           unit, port, PHY_DIAG_CTRL_SET));
   4799                 if (!SAL_BOOT_SIMULATION) {
   4800                     if (!(phy_access->access.lane_mask == 0)) {
   4801                         SOC_IF_ERROR_RETURN(portmod_pm_phy_control_set(phy_access, nof_phys,
   4802                                         op_cmd, ln_txparam, lane_map, PTR_TO_INT(arg)));
   4803                     }
   4804                 }
   4805             } else if (op_type == PHY_DIAG_CTRL_GET) {
   4806                 LOG_INFO(BSL_LS_SOC_PHY,
   4807                          (BSL_META_U(unit,
   4808                                      "portmod_phy_port_diag_ctrl: "
   4809                                      "u=%d p=%d PHY_DIAG_CTRL_GET 0x%x\n"),
   4810                           unit, port, PHY_DIAG_CTRL_GET));
   4811                 if (!SAL_BOOT_SIMULATION) {
   4812                     if (!(phy_access->access.lane_mask == 0)) {
   4813                         SOC_IF_ERROR_RETURN(portmod_pm_phy_control_get(phy_access,nof_phys,
   4814                                          op_cmd, ln_txparam, lane_map, (uint32 *)arg));
   4815                     } else {
   4816                         *(uint32 *)arg = 0;
   4817                     }
   4818                 }
   4819             } else {
   4820                 return (SOC_E_UNAVAIL);
   4821             }
   4822 
   4823             break;
   4824     }
   4825 
   4826     return (SOC_E_NONE);
   4827 }
   4828 
   4829 int portmod_phy_port_reset_get (int unit, int port, pm_info_t pm_info,
   4830                            int reset_mode, int opcode, int* direction)
   4831 {
   4832     phymod_core_access_t core_access[1+MAX_PHYN];
   4833     int nof_phys;
   4834     phymod_reset_direction_t reset_direction;
   4835 
   4836     SOC_INIT_FUNC_DEFS;
   4837 
   4838     _SOC_IF_ERR_EXIT
   4839         (portmod_port_chain_core_access_get(unit, port, pm_info,
   4840                                            core_access, (1+MAX_PHYN),
   4841                                            &nof_phys));
   4842 
   4843     _SOC_IF_ERR_EXIT
   4844         (portmod_port_phychain_core_reset_get(unit, core_access, nof_phys,
   4845                                               reset_mode,
   4846                                               &reset_direction));
   4847     *direction = reset_direction;
   4848 
   4849 exit:
   4850     SOC_FUNC_RETURN;
   4851 }
   4852 
   4853 int portmod_phy_port_reset_set (int unit, int port, pm_info_t pm_info,
   4854                            int reset_mode, int opcode, int direction)
   4855 {
   4856     phymod_core_access_t core_access[1+MAX_PHYN];
   4857     int nof_phys;
   4858 
   4859     SOC_INIT_FUNC_DEFS;
   4860 
   4861     _SOC_IF_ERR_EXIT
   4862         (portmod_port_chain_core_access_get(unit, port, pm_info,
   4863                                            core_access, (1+MAX_PHYN),
   4864                                            &nof_phys));
   4865 
   4866     _SOC_IF_ERR_EXIT
   4867         (portmod_port_phychain_core_reset_set(unit, core_access, nof_phys,
   4868                                               reset_mode,
   4869                                               direction));
   4870 exit:
   4871     SOC_FUNC_RETURN;
   4872 }
   4873 
   4874 int portmod_phy_port_prbs_config_set (int unit, int port, pm_info_t pm_info, 
   4875                                       portmod_prbs_mode_t mode, int flags, 
   4876                                       const phymod_prbs_t* config)
   4877 {
   4878     phymod_phy_access_t phy_access[1+MAX_PHYN];
   4879     int nof_phys;
   4880    
   4881     SOC_INIT_FUNC_DEFS;
   4882 
   4883     if(mode == 1 /*MAC*/) {
   4884         _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("MAC PRBS is not supported")));
   4885     }
   4886 
   4887     _SOC_IF_ERR_EXIT
   4888         (portmod_port_chain_phy_access_get(unit, port, pm_info,
   4889                                            phy_access ,(1+MAX_PHYN),
   4890                                            &nof_phys));
   4891     _SOC_IF_ERR_EXIT
   4892         (portmod_port_phychain_prbs_config_set(unit, phy_access, nof_phys, flags, config));
   4893 
   4894 exit:
   4895     SOC_FUNC_RETURN;
   4896 }
   4897 
   4898 int portmod_phy_port_prbs_config_get (int unit, int port, pm_info_t pm_info, 
   4899                                       portmod_prbs_mode_t mode, int flags, 
   4900                                       phymod_prbs_t* config)
   4901 {
   4902     phymod_phy_access_t phy_access[1+MAX_PHYN];
   4903     int nof_phys;
   4904     SOC_INIT_FUNC_DEFS;
   4905 
   4906     if(mode == 1 /*MAC*/) {
   4907         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   4908                       (_SOC_MSG("MAC PRBS is not supported for PM4x25")));
   4909     }
   4910 
   4911     _SOC_IF_ERR_EXIT
   4912         (portmod_port_chain_phy_access_get(unit, port, pm_info,
   4913                                            phy_access ,(1+MAX_PHYN),
   4914                                            &nof_phys));
   4915     _SOC_IF_ERR_EXIT
   4916         (portmod_port_phychain_prbs_config_get(unit, phy_access, nof_phys, flags, config));
   4917 
   4918 exit:
   4919     SOC_FUNC_RETURN;
   4920 }
   4921 
   4922 
   4923 int portmod_phy_port_prbs_enable_set(int unit, int port, pm_info_t pm_info, 
   4924                                      portmod_prbs_mode_t mode, int flags, int enable)
   4925 {
   4926     phymod_phy_access_t phy_access[1+MAX_PHYN];
   4927     int nof_phys;
   4928     SOC_INIT_FUNC_DEFS;
   4929 
   4930     if(mode == 1 /*MAC*/) {
   4931         _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (
   4932               _SOC_MSG("MAC PRBS is not supported for PM4x25")));
   4933     }
   4934 
   4935     _SOC_IF_ERR_EXIT
   4936         (portmod_port_chain_phy_access_get(unit, port, pm_info,
   4937                                            phy_access ,(1+MAX_PHYN),
   4938                                            &nof_phys));
   4939     _SOC_IF_ERR_EXIT
   4940         (portmod_port_phychain_prbs_enable_set(unit, phy_access, nof_phys, flags, enable));
   4941 
   4942 exit:
   4943     SOC_FUNC_RETURN;
   4944 }
   4945 
   4946 int portmod_phy_port_prbs_enable_get(int unit, int port, pm_info_t pm_info, 
   4947                                      portmod_prbs_mode_t mode, int flags, int* enable)
   4948 { 
   4949     phymod_phy_access_t phy_access[1+MAX_PHYN];
   4950     uint32 is_enabled;
   4951     int nof_phys;
   4952     SOC_INIT_FUNC_DEFS;
   4953 
   4954     if(mode == 1 /*MAC*/) {
   4955         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   4956                  (_SOC_MSG("MAC PRBS is not supported for PM4x25")));
   4957     }
   4958 
   4959     _SOC_IF_ERR_EXIT
   4960         (portmod_port_chain_phy_access_get(unit, port, pm_info,
   4961                                            phy_access ,(1+MAX_PHYN),
   4962                                            &nof_phys));
   4963 
   4964     _SOC_IF_ERR_EXIT
   4965         (portmod_port_phychain_prbs_enable_get(unit, phy_access, nof_phys, flags, &is_enabled));
   4966 
   4967     (*enable) = (is_enabled ? 1 : 0);
   4968 
   4969 exit:
   4970     SOC_FUNC_RETURN;
   4971 }
   4972 
   4973 
   4974 int portmod_phy_port_prbs_status_get(int unit, int port, pm_info_t pm_info, 
   4975                                      portmod_prbs_mode_t mode, int flags, 
   4976                                      phymod_prbs_status_t* status)
   4977 {
   4978     phymod_phy_access_t phy_access[1+MAX_PHYN];
   4979     int nof_phys;
   4980     SOC_INIT_FUNC_DEFS;
   4981 
   4982     if(mode == 1 /*MAC*/) {
   4983         _SOC_EXIT_WITH_ERR(SOC_E_PARAM,
   4984                 (_SOC_MSG("MAC PRBS is not supported for PM4x25")));
   4985     }
   4986 
   4987     _SOC_IF_ERR_EXIT
   4988         (portmod_port_chain_phy_access_get(unit, port, pm_info,
   4989                                            phy_access ,(1+MAX_PHYN),
   4990                                            &nof_phys));
   4991     _SOC_IF_ERR_EXIT
   4992         (portmod_port_phychain_prbs_status_get(unit, phy_access, nof_phys, flags, status));
   4993 
   4994 exit:
   4995     SOC_FUNC_RETURN;
   4996 }
   4997 
   4998 int portmod_phy_port_link_get(int unit, int port, pm_info_t pm_info, int* link)
   4999 {
   5000     phymod_phy_access_t phy_access[1+MAX_PHYN];
   5001     int nof_phys;
   5002 
   5003     SOC_INIT_FUNC_DEFS;
   5004 
   5005     _SOC_IF_ERR_EXIT
   5006         (portmod_port_chain_phy_access_get(unit, port, pm_info,
   5007                                            phy_access ,(1+MAX_PHYN),
   5008                                            &nof_phys));
   5009 
   5010     _SOC_IF_ERR_EXIT
   5011             (portmod_port_phychain_link_status_get(unit, port, phy_access, nof_phys, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, (uint32_t*) link));
   5012 
   5013 exit:
   5014     SOC_FUNC_RETURN;
   5015 }
   5016 
   5017 int portmod_phy_port_autoneg_status_get (int unit, int port, pm_info_t pm_info,
   5018                                     phymod_autoneg_status_t* an_status)
   5019 {
   5020     phymod_phy_access_t phy_access[1+MAX_PHYN];
   5021     int nof_phys;
   5022 
   5023     SOC_INIT_FUNC_DEFS;
   5024 
   5025     _SOC_IF_ERR_EXIT
   5026         (portmod_port_chain_phy_access_get(unit, port, pm_info,
   5027                                                phy_access ,(1+MAX_PHYN),
   5028                                                &nof_phys));
   5029     _SOC_IF_ERR_EXIT
   5030         (portmod_port_phychain_autoneg_status_get(unit, port, phy_access, nof_phys, an_status));
   5031 
   5032 exit:
   5033     SOC_FUNC_RETURN;
   5034 }
   5035 
   5036 int portmod_port_phychain_control_phy_timesync_set(int unit, int port, const phymod_phy_access_t* phy_access,
   5037                                                     const int chain_length,
   5038                                                     const portmod_port_control_phy_timesync_t type,
   5039                                                     uint64_t value)
   5040 {
   5041     int rv = PHYMOD_E_UNAVAIL;
   5042     int phy_index;
   5043     int is_legacy_phy = 0;
   5044 
   5045     PHYMOD_NULL_CHECK(phy_access);
   5046 
   5047     /* Most EXT first. */
   5048     phy_index = chain_length - 1;
   5049 
   5050     /* Most EXT */
   5051     rv = PHYMOD_E_UNAVAIL; 
   5052     while((PHYMOD_E_UNAVAIL == rv) && (phy_index >= 0)) {
   5053         is_legacy_phy = 0;
   5054 
   5055         /* if it is external phy, check to see if it is legacy phy. */
   5056         if (phy_index > 0) {
   5057             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   5058             if (rv != PHYMOD_E_NONE) return rv;
   5059         }
   5060 
   5061         if (is_legacy_phy) {
   5062             rv = portmod_port_legacy_control_phy_timesync_set(unit, port, type, value);
   5063         } else {
   5064             if (phy_access[phy_index].access.lane_mask) {
   5065                 rv = portmod_common_control_phy_timesync_set(&phy_access[phy_index], type, value);
   5066             } else {
   5067                 rv = PHYMOD_E_NONE;
   5068             }
   5069         }
   5070         phy_index--;
   5071     }
   5072     return(rv);
   5073 }
   5074 
   5075 int portmod_port_phychain_control_phy_timesync_get(int unit, int port, const phymod_phy_access_t* phy_access,
   5076                                                     const int chain_length,
   5077                                                     const portmod_port_control_phy_timesync_t type,
   5078                                                     uint64_t* value)
   5079 {
   5080     int rv = PHYMOD_E_UNAVAIL;
   5081     int phy_index;
   5082     int is_legacy_phy = 0;
   5083 
   5084     PHYMOD_NULL_CHECK(phy_access);
   5085 
   5086     /* Most EXT first. */
   5087     phy_index = chain_length - 1;
   5088 
   5089     /* Most EXT */
   5090     rv = PHYMOD_E_UNAVAIL; 
   5091     while((PHYMOD_E_UNAVAIL == rv) && (phy_index >= 0)) {
   5092         is_legacy_phy = 0;
   5093 
   5094         /* if it is external phy, check to see if it is legacy phy. */
   5095         if (phy_index > 0) {
   5096             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   5097             if (rv != PHYMOD_E_NONE) return rv;
   5098         }
   5099 
   5100         if (is_legacy_phy) {
   5101             rv = portmod_port_legacy_control_phy_timesync_get(unit, port, type, value);
   5102         } else {
   5103             if (phy_access[phy_index].access.lane_mask) {
   5104                 rv = portmod_common_control_phy_timesync_get(&phy_access[phy_index], type, value);
   5105             } else {
   5106                 rv = PHYMOD_E_NONE;
   5107             }
   5108         }
   5109         phy_index--;
   5110     }
   5111     return(rv);
   5112 }
   5113 
   5114 int portmod_port_phychain_medium_config_set(int unit, int port, soc_port_medium_t medium,
   5115                                              soc_phy_config_t* config)
   5116 {
   5117     return portmod_port_legacy_medium_config_set(unit, port, medium, config);
   5118 }
   5119 
   5120 int portmod_port_phychain_medium_config_get(int unit, int port, soc_port_medium_t medium,
   5121                                              soc_phy_config_t* config)
   5122 {
   5123     return portmod_port_legacy_medium_config_get(unit, port, medium, config);
   5124 }
   5125 
   5126 int portmod_port_phychain_medium_get(int unit, int port, soc_port_medium_t* medium)
   5127 {
   5128     return portmod_port_legacy_medium_get(unit, port, medium);
   5129 }
   5130 
   5131 int portmod_port_phychain_multi_get(int unit, int port, const phymod_phy_access_t* phy_access,
   5132                                     const int chain_length,
   5133                                     portmod_multi_get_t* multi_get) 
   5134 {
   5135     int rv = PHYMOD_E_UNAVAIL;
   5136     int phy_index;
   5137     int is_legacy_phy = 0;
   5138     phymod_multi_data_t  datablk ;  
   5139 
   5140     /* start from the most external phy. */
   5141     phy_index = chain_length - 1;
   5142 
   5143     /* Most EXT */
   5144     while((PHYMOD_E_UNAVAIL== rv) && (phy_index >= 0)) {
   5145         is_legacy_phy = 0;
   5146 
   5147         /* if it is external phy, check to see if it is legacy phy. */
   5148         if (phy_index > 0) {
   5149             rv = portmod_xphy_is_legacy_phy_get(unit, phy_access[phy_index].access.addr, &is_legacy_phy);
   5150             if (rv != PHYMOD_E_NONE) return rv;
   5151         }
   5152 
   5153         if (is_legacy_phy) {
   5154                 rv = portmod_port_legacy_multi_get(unit, port,
   5155                                                    multi_get->flags,
   5156                                                    multi_get->dev_addr,
   5157                                                    multi_get->offset,
   5158                                                    multi_get->max_size,
   5159                                                    multi_get->data,
   5160                                                    (int *) multi_get->actual_size);
   5161 
   5162         } else {
   5163             datablk.flags       = multi_get->flags;
   5164             datablk.dev_addr    = multi_get->dev_addr ;
   5165             datablk.offset      = multi_get->offset ;
   5166             datablk.max_size    = multi_get->max_size ;
   5167             datablk.data        = multi_get->data ;
   5168             datablk.actual_size = multi_get->actual_size ;
   5169 
   5170             rv = phymod_phy_multi_get(&phy_access[phy_index], &datablk) ;
   5171         }
   5172         phy_index--;
   5173     }
   5174     return(rv);
   5175 }
   5176 
   5177 int portmod_port_phychain_master_set(int unit, int port, pm_info_t pm_info, int master_mode)
   5178 {
   5179     phymod_phy_access_t phy_access_arr[1+MAX_PHYN];
   5180     int xphy_id;
   5181     int is_legacy_phy;
   5182     int nof_phys;
   5183     phymod_master_mode_t ms_mode = phymodMSNone;
   5184 
   5185     SOC_INIT_FUNC_DEFS;
   5186 
   5187     _SOC_IF_ERR_EXIT
   5188         (portmod_port_chain_phy_access_get(unit, port, pm_info,
   5189                                            phy_access_arr ,(1+MAX_PHYN),
   5190                                            &nof_phys));
   5191 
   5192     if (nof_phys == 1) {
   5193         switch (master_mode) {
   5194             case SOC_PORT_MS_SLAVE:
   5195                 ms_mode = phymodMSSlave;
   5196                 break;
   5197             case SOC_PORT_MS_MASTER:
   5198                 ms_mode = phymodMSMaster;
   5199                 break;
   5200             case SOC_PORT_MS_AUTO:
   5201                 ms_mode = phymodMSAuto;
   5202                 break;
   5203             default:
   5204                 return PHYMOD_E_PARAM;
   5205         }
   5206         _SOC_IF_ERR_EXIT
   5207             (phymod_phy_master_set(&phy_access_arr[0], ms_mode));
   5208     } else {
   5209         xphy_id = phy_access_arr[nof_phys-1].access.addr;
   5210         _SOC_IF_ERR_EXIT
   5211             (portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy));
   5212 
   5213         if (is_legacy_phy) {
   5214             _SOC_IF_ERR_EXIT
   5215                 (portmod_port_legacy_master_set(unit, port, master_mode));
   5216         } else {
   5217             return PHYMOD_E_UNAVAIL;
   5218         }
   5219     }
   5220 
   5221 exit:
   5222     SOC_FUNC_RETURN;
   5223 }
   5224 
   5225 /* 
   5226  * This function retrieves the SGMII AN mode (master/slave/auto/none).
   5227  * Currently it only retrieves the register value for the legacy PHYs.
   5228  * For internal PHY, master mode is hard-coded as slave mode.
   5229  */
   5230 int portmod_port_phychain_master_get(int unit, int port, pm_info_t pm_info, int* master_mode)
   5231 {
   5232     phymod_phy_access_t phy_access_arr[1+MAX_PHYN];
   5233     int xphy_id;
   5234     int is_legacy_phy;
   5235     int nof_phys;
   5236     int rv = PHYMOD_E_NONE;
   5237     phymod_master_mode_t ms_mode = phymodMSNone;
   5238 
   5239     SOC_INIT_FUNC_DEFS;
   5240 
   5241     _SOC_IF_ERR_EXIT
   5242         (portmod_port_chain_phy_access_get(unit, port, pm_info,
   5243                                            phy_access_arr ,(1+MAX_PHYN),
   5244                                            &nof_phys));
   5245 
   5246     if (nof_phys == 1) {
   5247         rv = phymod_phy_master_get(&phy_access_arr[0], &ms_mode);
   5248         /*The internal PHY is mainly in slave mode */
   5249         if (rv == PHYMOD_E_UNAVAIL) {
   5250             *master_mode = SOC_PORT_MS_SLAVE;
   5251         } else {
   5252             switch (ms_mode) {
   5253                 case phymodMSNone:
   5254                     *master_mode = SOC_PORT_MS_NONE;
   5255                     break;
   5256                 case phymodMSSlave:
   5257                     *master_mode = SOC_PORT_MS_SLAVE;
   5258                     break;
   5259                 case phymodMSMaster:
   5260                     *master_mode = SOC_PORT_MS_MASTER;
   5261                     break;
   5262                 case phymodMSAuto:
   5263                     *master_mode = SOC_PORT_MS_AUTO;
   5264                     break;
   5265                 default:
   5266                     *master_mode = SOC_PORT_MS_NONE;
   5267                     break;
   5268             }
   5269         }
   5270     } else {
   5271         xphy_id = phy_access_arr[nof_phys-1].access.addr;
   5272         _SOC_IF_ERR_EXIT
   5273             (portmod_xphy_is_legacy_phy_get(unit, xphy_id, &is_legacy_phy));
   5274 
   5275         if (is_legacy_phy) {
   5276             _SOC_IF_ERR_EXIT
   5277                 (portmod_port_legacy_master_get(unit, port, master_mode));
   5278         } else {
   5279             /*
   5280              * PHYMOD-based ext PHYs have not implemented the matser_get API,
   5281              * so we follow the convention of bcmi_esw_portctrl_master_get()
   5282              * to make master_mode BCM_PORT_MS_NONE when the API is not supported.
   5283              * Otherwise there will be error messages popping up during init
   5284              * and ps.
   5285              */
   5286             *master_mode = BCM_PORT_MS_NONE;
   5287         }
   5288     }
   5289 
   5290 exit:
   5291     SOC_FUNC_RETURN;
   5292 }