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

eyescan.c (87866B)


      1 /* 
      2  * 
      3  *
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  *
      8  * SOC EYESCAN
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <sal/types.h>
     14 #include <soc/eyescan.h>
     15 #include <soc/drv.h>
     16 #include <soc/error.h>
     17 #include <soc/mem.h>
     18 #include <soc/phy/phyctrl.h>
     19 
     20 #ifdef PHYMOD_SUPPORT
     21 #include <phymod/phymod_diagnostics.h>
     22 #include <phymod/phymod_diag.h>
     23 #endif
     24 
     25 #ifdef PORTMOD_SUPPORT
     26 #include <soc/portmod/portmod.h>
     27 #endif
     28 
     29 #ifndef __KERNEL__
     30 #include <math.h> 
     31 #endif /* #ifndef __KERNEL__ */
     32 
     33 STATIC soc_port_phy_eyescan_counter_cb_t counter_func[SOC_MAX_NUM_DEVICES][socPortPhyEyescanNofCounters] = {{{0}}};
     34 
     35 int 
     36 soc_port_phy_eyescan_counter_register(int unit, soc_port_phy_eyscan_counter_t counter, soc_port_phy_eyescan_counter_cb_t* cf)
     37 {
     38     if (!SOC_UNIT_VALID(unit)) {
     39         LOG_ERROR(BSL_LS_SOC_PHY,
     40                   (BSL_META_U(unit,
     41                               "Invalid unit\n")));
     42         return SOC_E_UNIT;
     43     }
     44 
     45     if(counter >= socPortPhyEyescanNofCounters || counter < 0) {
     46         LOG_ERROR(BSL_LS_SOC_PHY,
     47                   (BSL_META_U(unit,
     48                               "Counter %d isn't supported\n"), counter));
     49         return SOC_E_PARAM;
     50     }
     51 
     52     if(NULL == cf) { /*clear callbacks*/
     53         counter_func[unit][counter].clear_func = NULL;
     54         counter_func[unit][counter].get_func = NULL;
     55     } else {
     56         counter_func[unit][counter] = *cf;
     57     }
     58 
     59     return SOC_E_NONE;
     60 }
     61 
     62 STATIC int 
     63 soc_port_phy_eyescan_check_bounds(int unit, soc_port_t port, uint32 inst, int flags, soc_port_phy_eyscan_counter_t counter, soc_port_phy_eye_bounds_t* bounds)
     64 {
     65     int vmax, vmin, l_hmax, r_hmax;
     66     int locked;
     67     int rv = SOC_E_NONE;
     68 
     69     if((socPortPhyEyescanCounterRelativePhy!=counter) && bounds->vertical_min<0) {
     70         LOG_CLI((BSL_META_U(unit,
     71                             "Counter mode doesn't support negative vertical_min. Updated to 0.\n")));
     72         bounds->vertical_min = 0;
     73     } 
     74     if(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY) {
     75         bounds->horizontal_min = 0;
     76         bounds->horizontal_max = 0;
     77     }
     78 
     79     MIIM_LOCK(unit);
     80     locked = 1;
     81 
     82     if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)){
     83         rv = soc_phyctrl_diag_ctrl(unit, port, inst,
     84                                    PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_GET_MAX_LEFT_HOFFSET, (int *) (&l_hmax));
     85         if (SOC_FAILURE(rv)) {
     86             LOG_ERROR(BSL_LS_SOC_PHY,
     87                       (BSL_META_U(unit,
     88                                   "%s\n"), soc_errmsg(rv)));
     89             goto exit;
     90         }
     91         rv = soc_phyctrl_diag_ctrl(unit, port, inst,
     92                                    PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_GET_MAX_RIGHT_HOFFSET, (int *) (&r_hmax));
     93         if (SOC_FAILURE(rv)) {
     94             LOG_ERROR(BSL_LS_SOC_PHY,
     95                       (BSL_META_U(unit,
     96                                   "%s\n"), soc_errmsg(rv)));
     97             goto exit;
     98         }
     99     }
    100 
    101     rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    102                                PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_GET_MIN_VOFFSET, (int *) (&vmin));
    103     if (SOC_FAILURE(rv)) {
    104         LOG_ERROR(BSL_LS_SOC_PHY,
    105                   (BSL_META_U(unit,
    106                               "%s\n"), soc_errmsg(rv)));
    107         goto exit;
    108     }
    109     rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    110                                PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_GET_MAX_VOFFSET, (int *) (&vmax));
    111     if (SOC_FAILURE(rv)) {
    112         LOG_ERROR(BSL_LS_SOC_PHY,
    113                   (BSL_META_U(unit,
    114                               "%s\n"), soc_errmsg(rv)));
    115         goto exit;
    116     }
    117 
    118     locked = 0;
    119     MIIM_UNLOCK(unit);
    120 
    121     if(bounds->vertical_min < vmin){
    122         LOG_CLI((BSL_META_U(unit,
    123                             "vertical_min smaller than min available. Updated to %d.\n"), vmin));
    124         bounds->vertical_min = vmin;
    125     }
    126     if (bounds->vertical_max > vmax) {
    127         LOG_CLI((BSL_META_U(unit,
    128                             "vertical_max larger than max available. Updated to %d.\n"), vmax));
    129         bounds->vertical_max = vmax;
    130     }
    131 
    132     if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)){
    133         if(bounds->horizontal_min < l_hmax){
    134             LOG_CLI((BSL_META_U(unit,
    135                                 "horizontal_min smaller than min available. Updated to %d.\n"), l_hmax));
    136             bounds->horizontal_min = l_hmax;
    137         }
    138         if (bounds->horizontal_max > r_hmax) {
    139             LOG_CLI((BSL_META_U(unit,
    140                                 "horizontal_max larger than max available. Updated to %d.\n"), r_hmax));
    141             bounds->horizontal_max = r_hmax;   
    142         }
    143     }
    144 
    145     if(bounds->vertical_min < -1*SOC_PORT_PHY_EYESCAN_V_INDEX){
    146         LOG_CLI((BSL_META_U(unit,
    147                             "vertical_min smaller than min available. Updated to %d.\n"), -1*SOC_PORT_PHY_EYESCAN_V_INDEX));
    148         bounds->vertical_min = -1*SOC_PORT_PHY_EYESCAN_V_INDEX;
    149     }
    150     if (bounds->vertical_max > SOC_PORT_PHY_EYESCAN_V_INDEX) {
    151         LOG_CLI((BSL_META_U(unit,
    152                             "vertical_max larger than max available. Updated to %d.\n"), SOC_PORT_PHY_EYESCAN_V_INDEX));
    153         bounds->vertical_max = SOC_PORT_PHY_EYESCAN_V_INDEX;
    154     }
    155 
    156     if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)){
    157         if(bounds->horizontal_min < -1*SOC_PORT_PHY_EYESCAN_H_INDEX){
    158             LOG_CLI((BSL_META_U(unit,
    159                                 "horizontal_min smaller than min available. Updated to %d.\n"), -1*SOC_PORT_PHY_EYESCAN_H_INDEX));
    160             bounds->horizontal_min = -1*SOC_PORT_PHY_EYESCAN_H_INDEX;
    161         }
    162         if (bounds->horizontal_max > SOC_PORT_PHY_EYESCAN_H_INDEX) {
    163             LOG_CLI((BSL_META_U(unit,
    164                                 "horizontal_max larger than max available. Updated to %d.\n"), SOC_PORT_PHY_EYESCAN_H_INDEX));
    165             bounds->horizontal_max = SOC_PORT_PHY_EYESCAN_H_INDEX;   
    166         }
    167     }
    168 
    169 exit:
    170     if (locked) {
    171         MIIM_UNLOCK(unit);
    172     }
    173     return rv;
    174 }
    175 
    176 
    177 STATIC int 
    178 soc_port_phy_eyescan_enable(int unit, uint32 inst, int flags, soc_port_t port, 
    179                             soc_port_phy_eyscan_counter_t counter, int enable, int* voffset)
    180 {
    181     int  data;
    182     int p1_mapped[] = {0,1,3,2,4,5,7,6,8,9,11,10,12,13,15,14,16,17,19,18,20,21,23,22,24,25,27,26,28,29,31,30};
    183     int hoffset_init=0;
    184     int rv = SOC_E_NONE;
    185 
    186     MIIM_LOCK(unit);
    187 
    188     switch(counter) {
    189     case socPortPhyEyescanCounterRelativePhy:
    190         if(enable) {
    191             rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    192                                        PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_ENABLE_LIVELINK, (void *) (0));
    193             if (SOC_FAILURE(rv)) {
    194                 LOG_ERROR(BSL_LS_SOC_PHY,
    195                           (BSL_META_U(unit,
    196                                       "%s\n"), soc_errmsg(rv)));
    197                 goto exit;
    198             }
    199             rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    200                                        PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_GET_INIT_VOFFSET, voffset);
    201             if (SOC_FAILURE(rv)) {
    202                 LOG_ERROR(BSL_LS_SOC_PHY,
    203                           (BSL_META_U(unit,
    204                                       "%s\n"), soc_errmsg(rv)));
    205                 goto exit;
    206             }
    207 
    208             /* use the mapped P1 value */
    209             data = *voffset & 0x1f;
    210             data = p1_mapped[data];
    211             data |= (*voffset) & 0x20;
    212             *voffset = data;
    213 
    214         } else {
    215             if(SRD_EYESCAN_INVALID_VOFFSET != *voffset) {
    216                 if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)) {
    217                     rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    218                                                PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_SET_HOFFSET, &hoffset_init);
    219                     if (SOC_FAILURE(rv)) {
    220                         LOG_ERROR(BSL_LS_SOC_PHY,
    221                                   (BSL_META_U(unit,
    222                                               "%s\n"), soc_errmsg(rv)));
    223                         goto exit;
    224                     }
    225                 }
    226                 rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    227                                            PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_SET_VOFFSET, (int *) voffset);
    228                 if (SOC_FAILURE(rv)) {
    229                     LOG_ERROR(BSL_LS_SOC_PHY,
    230                               (BSL_META_U(unit,
    231                                           "%s\n"), soc_errmsg(rv)));
    232                     goto exit;
    233                 }
    234             }
    235             rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    236                                        PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_DISABLE_LIVELINK, (void *) (0));
    237             if (SOC_FAILURE(rv)) {
    238                 LOG_ERROR(BSL_LS_SOC_PHY,
    239                           (BSL_META_U(unit,
    240                                       "%s\n"), soc_errmsg(rv)));
    241                 goto exit;
    242             }
    243         }
    244         break;
    245     case socPortPhyEyescanCounterPrbsPhy:
    246     case socPortPhyEyescanCounterPrbsMac:
    247     case socPortPhyEyescanCounterCrcMac:
    248     case socPortPhyEyescanCounterBerMac: 
    249     default:
    250         if(enable) {
    251             rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    252                                        PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_ENABLE_DEADLINK, (void *) (0));
    253             if (SOC_FAILURE(rv)) {
    254                 LOG_ERROR(BSL_LS_SOC_PHY,
    255                           (BSL_META_U(unit,
    256                                       "%s\n"), soc_errmsg(rv)));
    257                 goto exit;
    258             }
    259         } else {
    260             rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    261                                        PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_SET_HOFFSET,  &hoffset_init);
    262             if (SOC_FAILURE(rv)) {
    263                 LOG_ERROR(BSL_LS_SOC_PHY,
    264                           (BSL_META_U(unit,
    265                                       "%s\n"), soc_errmsg(rv)));
    266                 goto exit;
    267             }
    268             rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    269                                        PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_SET_VOFFSET,  &hoffset_init);
    270             if (SOC_FAILURE(rv)) {
    271                 LOG_ERROR(BSL_LS_SOC_PHY,
    272                           (BSL_META_U(unit,
    273                                       "%s\n"), soc_errmsg(rv)));
    274                 goto exit;
    275             }
    276             rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    277                                        PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_DISABLE_DEADLINK, (void *) (0));
    278             if (SOC_FAILURE(rv)) {
    279                 LOG_ERROR(BSL_LS_SOC_PHY,
    280                           (BSL_META_U(unit,
    281                                       "%s\n"), soc_errmsg(rv)));
    282                 goto exit;
    283             }
    284         }
    285         break;
    286     }
    287 
    288 exit:
    289     MIIM_UNLOCK(unit);
    290     return rv;
    291 }
    292 
    293 STATIC int 
    294 soc_port_phy_eyescan_counter_clear(int unit, soc_port_t port, uint32 inst, soc_port_phy_eyscan_counter_t counter, sal_usecs_t* start_time)
    295 {
    296     uint32 error;
    297     int rv = SOC_E_NONE;
    298 
    299      if(NULL != counter_func[unit][counter].get_func) {
    300         counter_func[unit][counter].clear_func(unit, port);
    301     } else {
    302         switch(counter) {
    303         case socPortPhyEyescanCounterRelativePhy:
    304             rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    305                                        PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_CLEAR_LIVELINK, (void *) (0));
    306             if (SOC_FAILURE(rv)) {
    307                 LOG_ERROR(BSL_LS_SOC_PHY,
    308                           (BSL_META_U(unit,
    309                                       "%s\n"), soc_errmsg(rv)));
    310                 return rv;
    311             }
    312             break;
    313         case socPortPhyEyescanCounterPrbsPhy:
    314             rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    315                                        PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_READ_DEADLINK, &error);
    316             if (SOC_FAILURE(rv)) {
    317                 LOG_ERROR(BSL_LS_SOC_PHY,
    318                           (BSL_META_U(unit,
    319                                       "%s\n"), soc_errmsg(rv)));
    320                 return rv;
    321             }
    322             break;
    323         default:
    324             LOG_ERROR(BSL_LS_SOC_PHY,
    325                       (BSL_META_U(unit,
    326                                   "counter isn't supported by the device\n")));
    327             return SOC_E_PARAM;
    328             break;
    329         }
    330     }
    331 
    332     *start_time = sal_time_usecs();
    333 
    334     return rv;
    335 }
    336 
    337 STATIC int 
    338 soc_port_phy_eyescan_start(int unit,  soc_port_t port, uint32 inst, soc_port_phy_eyscan_counter_t counter)
    339 {
    340     int rv = SOC_E_NONE;
    341 
    342     switch(counter) {
    343     case socPortPhyEyescanCounterRelativePhy:
    344         rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    345                                    PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_START_LIVELINK, (void *) (0));
    346         if (SOC_FAILURE(rv)) {
    347             LOG_ERROR(BSL_LS_SOC_PHY,
    348                       (BSL_META_U(unit,
    349                                   "%s\n"), soc_errmsg(rv)));
    350         }
    351         break;
    352     case socPortPhyEyescanCounterPrbsMac:
    353     case socPortPhyEyescanCounterPrbsPhy:
    354     case socPortPhyEyescanCounterCrcMac:
    355     case socPortPhyEyescanCounterBerMac: 
    356     default:
    357         rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    358                                    PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_START_DEADLINK, (void *) (0));
    359         if (SOC_FAILURE(rv)) {
    360             LOG_ERROR(BSL_LS_SOC_PHY,
    361                       (BSL_META_U(unit,
    362                                   "%s\n"), soc_errmsg(rv)));
    363         }
    364         break;
    365     }
    366 
    367     return rv;
    368 }
    369 
    370 STATIC int 
    371 soc_port_phy_eyescan_stop(int unit, soc_port_t port, uint32 inst, soc_port_phy_eyscan_counter_t counter, sal_usecs_t* end_time)
    372 {
    373     int rv = SOC_E_NONE;
    374 
    375     switch(counter) {
    376     case socPortPhyEyescanCounterRelativePhy:
    377         rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    378                                    PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_STOP_LIVELINK, (void *) (0));
    379         if (SOC_FAILURE(rv)) {
    380             LOG_ERROR(BSL_LS_SOC_PHY,
    381                       (BSL_META_U(unit,
    382                                   "%s\n"), soc_errmsg(rv)));
    383             return rv;
    384         }
    385         break;
    386     default:
    387         break;
    388     }
    389 
    390     *end_time = sal_time_usecs();
    391 
    392     return rv;
    393 }
    394 
    395 STATIC int 
    396 soc_port_phy_eyescan_counter_get(int unit, soc_port_t port, uint32 inst, soc_port_phy_eyscan_counter_t counter, uint32* err_count)
    397 {
    398     int rv = SOC_E_NONE;
    399 
    400     if(NULL != counter_func[unit][counter].get_func) {
    401         counter_func[unit][counter].get_func(unit, port, err_count);
    402     } else {
    403 
    404         switch(counter) {
    405         case socPortPhyEyescanCounterRelativePhy:
    406             rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    407                                        PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_READ_LIVELINK, err_count);
    408             if (SOC_FAILURE(rv)) {
    409                 LOG_ERROR(BSL_LS_SOC_PHY,
    410                           (BSL_META_U(unit,
    411                                       "%s\n"), soc_errmsg(rv)));
    412             }
    413             break;
    414         case socPortPhyEyescanCounterPrbsPhy:
    415             rv = soc_phyctrl_diag_ctrl(unit, port, inst,
    416                                        PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_READ_DEADLINK, err_count);
    417             if (SOC_FAILURE(rv)) {
    418                 LOG_ERROR(BSL_LS_SOC_PHY,
    419                           (BSL_META_U(unit,
    420                                       "%s\n"), soc_errmsg(rv)));
    421             }
    422             break;
    423         default:
    424             rv = SOC_E_PARAM;
    425             LOG_ERROR(BSL_LS_SOC_PHY,
    426                       (BSL_META_U(unit,
    427                                   "Counter isn't supported by the device\n")));
    428             break;
    429         }
    430     }
    431 
    432     return rv;
    433 }
    434 
    435 #ifdef PHYMOD_SUPPORT
    436 int _soc_port_phy_is_glue_driver(int unit, soc_port_t port)
    437 {
    438     phy_ctrl_t *pc;
    439 
    440     pc = EXT_PHY_SW_STATE(unit, port);
    441     if (!pc) {
    442         return(0);
    443     }
    444     if (!pc->pd) {
    445         return(0);
    446     }
    447 
    448     /* Checking id for Sesto */
    449     if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5290)) {
    450         return(1);
    451     }
    452 
    453     /* Checking id for furia */
    454     if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5230)) {
    455         return(1);
    456     }
    457 
    458     /* Checking id for madura */
    459     if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x52b0)) {
    460         return(1);
    461     }
    462 
    463     /* Checking id for Qudra28 */
    464     if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5250)) {
    465         return(1);
    466     }
    467 
    468     /* Checking id for Dino */
    469     if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5390)) {
    470         return(1);
    471     }
    472 
    473     return(0);
    474 }
    475 #endif
    476 
    477 int _soc_port_phy_eyescan_run( 
    478     int unit, 
    479     uint32 inst,            /* phy instance containing phy number and interface */
    480     int flags, 
    481     soc_port_phy_eyescan_params_t* params, 
    482     uint32 nof_ports,
    483     soc_port_t* ports,
    484     int* lane_num,
    485     soc_port_phy_eyescan_results_t* results /*array of result per port*/) 
    486 {
    487 #if 0
    488     int port=0,index=0;
    489 #endif
    490     int h,v,j;
    491     int under_threshold, first_run, default_sample_time;
    492     int total_time, desired_time, time_before;
    493     sal_usecs_t* start_time = NULL;
    494     sal_usecs_t end_time = 0;
    495     uint32 err_count;
    496     int* v_init_offset = NULL;
    497     soc_port_t* local_ports = NULL;
    498     int* local_lane_num = NULL;
    499     pbmp_t valid_ports_bitmap;
    500     uint32 is_enable;
    501 #ifdef PHYMOD_SUPPORT
    502     uint32 done;
    503 #endif
    504     int dev, intf;
    505     int rv = SOC_E_NONE;
    506 
    507     /*validate input*/
    508     if (!SOC_UNIT_VALID(unit)) {
    509         LOG_ERROR(BSL_LS_SOC_PHY,
    510                   (BSL_META_U(unit,
    511                               "Invalid unit\n")));
    512         return SOC_E_UNIT;
    513     }
    514 
    515     if (params == NULL || ports == NULL || results == NULL) {
    516         LOG_ERROR(BSL_LS_SOC_PHY,
    517                   (BSL_META_U(unit,
    518                               "Null parameter\n")));
    519         return SOC_E_PARAM;
    520     }
    521 
    522     if(params->counter >= socPortPhyEyescanNofCounters || params->counter < 0) {
    523         LOG_ERROR(BSL_LS_SOC_PHY,
    524                   (BSL_META_U(unit,
    525                               "Counter %d isn't supported\n"), params->counter));
    526         return SOC_E_PARAM;
    527     }
    528 
    529     /*allocate & initialize local_ports array*/
    530     local_ports = (soc_port_t*)sal_alloc(sizeof(soc_port_t)*nof_ports,"eyecan local ports");
    531     for (j = 0; j < nof_ports; j++) {
    532         local_ports[j] = -1;
    533     }
    534     if(NULL == local_ports) {
    535         rv = SOC_E_MEMORY;
    536         LOG_ERROR(BSL_LS_SOC_PHY,
    537                   (BSL_META_U(unit,
    538                               "Failed to allocate local_ports array\n")));
    539         goto exit;
    540     }
    541 
    542     /*allocate & initialize local_lane_num array*/
    543     local_lane_num = (int*)sal_alloc(sizeof(int)*nof_ports,"eyecan local_lane_num");
    544     if(NULL == local_lane_num) {
    545         rv = SOC_E_MEMORY;
    546         LOG_ERROR(BSL_LS_SOC_PHY,
    547                   (BSL_META_U(unit,
    548                               "Failed to allocate local_lane_num array\n")));
    549         goto exit;
    550     }
    551 
    552     /*get valid ports*/
    553     SOC_PBMP_ASSIGN(valid_ports_bitmap, SOC_INFO(unit).port.bitmap);
    554 
    555     intf = PHY_DIAG_INTF_DFLT;
    556     dev = PHY_DIAG_INST_DEV(inst);
    557     if (dev == PHY_DIAG_DEV_EXT) {
    558         intf = PHY_DIAG_INST_INTF(inst);
    559     }
    560 
    561     for(j = 0 ; j < nof_ports ; j++) {
    562         if (SOC_PBMP_MEMBER(valid_ports_bitmap, ports[j])) {
    563             if (dev == PHY_DIAG_DEV_EXT) {
    564                 if (lane_num != NULL) {
    565                     rv = soc_phyctrl_redirect_control_get(unit, ports[j], dev, lane_num[j],
    566                         (intf == PHY_DIAG_INTF_SYS), SOC_PHY_CONTROL_RX_SEQ_DONE, 
    567                         &is_enable);
    568                 } else {
    569                     rv = soc_phyctrl_redirect_control_get(unit, ports[j], dev, -1,
    570                         (intf == PHY_DIAG_INTF_SYS),
    571                         SOC_PHY_CONTROL_RX_SEQ_DONE, &is_enable);
    572                 }
    573                 if (SOC_FAILURE(rv)) {
    574                     LOG_ERROR(BSL_LS_SOC_PHY,
    575                               (BSL_META_U(unit,
    576                                           "%s\n"), soc_errmsg(rv)));
    577                     goto exit;
    578                 }
    579             } else {
    580                 rv = soc_phyctrl_control_get(unit, ports[j],
    581                                              SOC_PHY_CONTROL_RX_SEQ_DONE,
    582                                              &is_enable);
    583                 if (SOC_FAILURE(rv)) {
    584                     LOG_ERROR(BSL_LS_SOC_PHY,
    585                               (BSL_META_U(unit,
    586                                           "%s\n"), soc_errmsg(rv)));
    587                     goto exit;
    588                 }
    589             }
    590             if(is_enable) {
    591                 local_ports[j] = ports[j];
    592             } else {
    593                 /*do not run eyescan*/
    594                 local_ports[j] = -1;
    595             }
    596         } else {
    597             rv = SOC_E_PORT;
    598             LOG_ERROR(BSL_LS_SOC_PHY,
    599                       (BSL_META_U(unit,
    600                                   "Invalid port %d\n"), ports[j]));
    601             goto exit;
    602         }
    603     }
    604 
    605 #ifdef PHYMOD_SUPPORT
    606     /*enable BER proj*/
    607     for (j = 0; j < nof_ports; j++) {
    608         /*if serdes is unlock continue*/
    609         if (local_ports[j] == -1) continue;
    610         if(_soc_port_phy_is_glue_driver(unit, local_ports[j]) && (params->type == 4)) {
    611             rv = soc_phyctrl_diag_ctrl(unit, local_ports[j], inst,
    612                                PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_BER, (void *) (params));
    613             if (SOC_FAILURE(rv)) {
    614                 LOG_ERROR(BSL_LS_SOC_PHY,
    615                           (BSL_META_U(unit,
    616                                       "%s\n"), soc_errmsg(rv)));
    617                 goto exit;
    618             }
    619             /* label this port has been handled */
    620             local_ports[j] = -1;
    621         }
    622     }
    623 
    624     done = 1;
    625     for (j = 0; j < nof_ports; j++) {
    626         if(local_ports[j] != -1) {
    627            done = 0;
    628            break;
    629         }
    630     }
    631     if(done == 1) {
    632         goto exit;
    633     }
    634 #endif
    635 
    636     /* check if the lane num is NULL */
    637     /* pc->lane_num used to indicate which lane to focus on */
    638     /* in the leagcy driver                                 */
    639     if (lane_num != NULL) {
    640         phy_ctrl_t *pc;
    641         for(j = 0 ; j < nof_ports ; j++) {
    642             if (local_ports[j] == -1) continue;
    643             pc = INT_PHY_SW_STATE(unit, local_ports[j]);
    644             local_lane_num[j] = pc->lane_num;
    645             if (pc->phy_mode == PHYCTRL_DUAL_LANE_PORT) {
    646                 pc->lane_num += lane_num[j];
    647             } else {
    648                 pc->lane_num = lane_num[j];
    649             }
    650         }
    651     }
    652 
    653     /*allocate start_time array*/
    654     start_time = (uint32*)sal_alloc(sizeof(sal_usecs_t)*nof_ports,"eyecan start time");
    655     if(NULL == start_time) {
    656         rv = SOC_E_MEMORY;
    657         LOG_ERROR(BSL_LS_SOC_PHY,
    658                   (BSL_META_U(unit,
    659                               "Failed to allocate start_time array\n")));
    660         goto exit;
    661     }
    662 
    663     /*allocate v_init_offset array*/
    664     v_init_offset = (int*)sal_alloc(sizeof(int)*nof_ports,"eyecan v_init_offset");
    665     if(NULL == v_init_offset) {
    666         rv = SOC_E_MEMORY;
    667         LOG_ERROR(BSL_LS_SOC_PHY,
    668                   (BSL_META_U(unit,
    669                               "Failed to allocate v_init_offset array\n")));
    670         goto exit;
    671     }
    672     for(j = 0 ; j < nof_ports ; j++) {
    673         v_init_offset[j] = SRD_EYESCAN_INVALID_VOFFSET;
    674     }
    675 
    676     /*enable eyescan*/
    677     for (j = 0; j < nof_ports; j++) {
    678         /*if serdes is unlock continue*/
    679         if (local_ports[j] == -1) continue;
    680         rv = soc_port_phy_eyescan_enable(unit, inst, flags, local_ports[j], params->counter, 1, &(v_init_offset[j]));
    681         if (SOC_FAILURE(rv)) {
    682             LOG_ERROR(BSL_LS_SOC_PHY,
    683                       (BSL_META_U(unit,
    684                                   "%s\n"), soc_errmsg(rv)));
    685             goto exit;
    686         }
    687     }
    688 
    689     sal_usleep(100000);
    690     /*check bounds*/
    691     for (j = 0; j < nof_ports; j++) {
    692         /*if serdes is unlock continue*/
    693         if (local_ports[j] == -1) continue;
    694         rv = soc_port_phy_eyescan_check_bounds(unit, local_ports[j], inst, flags, params->counter, &(params->bounds));
    695         if (SOC_FAILURE(rv)) {
    696             LOG_ERROR(BSL_LS_SOC_PHY,
    697                       (BSL_META_U(unit,
    698                                   "%s\n"), soc_errmsg(rv)));
    699             goto exit;
    700         }
    701     }
    702 
    703     default_sample_time = params->sample_time;
    704 
    705     /*scan*/
    706     for(h = params->bounds.horizontal_min; h <= params->bounds.horizontal_max; h++) {
    707         if(h % params->sample_resolution != 0) {
    708             if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)){
    709                 continue;
    710             }
    711         }
    712         desired_time = 0;
    713         params->sample_time = default_sample_time;
    714 
    715         for(v = params->bounds.vertical_max; v >= params->bounds.vertical_min; v--) {
    716             if(v % params->sample_resolution != 0) {
    717                 continue;
    718             }
    719 
    720             if (flags & SRD_EYESCAN_FLAG_DSC_PRINT) {
    721                 LOG_CLI((BSL_META_U(unit,
    722                                     "\nStarting BER msmt at offset: v=%d h=%d\n"), v, h));
    723             }
    724 
    725             under_threshold = params->nof_threshold_links;
    726             first_run = 1;     
    727             total_time = 0;   
    728             for (j = 0; j < nof_ports; j++) {
    729                 /*if serdes is unlock continue*/
    730                 if (local_ports[j] == -1) continue;
    731 
    732                 results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] = 0;
    733                 results[j].error_count[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] = 0;            
    734             }
    735 
    736             while ((under_threshold >= params->nof_threshold_links) && (params->sample_time <= params->time_upper_bound)) {
    737                 under_threshold = 0;
    738                 if (first_run) {
    739                     desired_time = params->sample_time;
    740                     total_time = params->sample_time;
    741                 } else {
    742                     if ((desired_time >= params->time_upper_bound) || (total_time >= params->time_upper_bound)) {
    743                         params->sample_time = (params->time_upper_bound + 1);
    744                         break;
    745                     } 
    746                     desired_time = desired_time * TIME_MULTIPLIER;
    747                     params->sample_time = desired_time - total_time;
    748                     if (params->sample_time > params->time_upper_bound) {
    749                         params->sample_time = params->time_upper_bound - total_time;
    750                     }
    751                     total_time += params->sample_time;
    752                 }
    753 
    754                 for (j = 0; (j < nof_ports); j++) {
    755                     /*if serdes is unlock continue*/
    756                     if (local_ports[j] == -1) continue;
    757 
    758                     if (first_run) {
    759                         /*set vertical and horizinal*/
    760                         if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)) {
    761                             rv = soc_phyctrl_diag_ctrl(unit, local_ports[j], inst,
    762                                                        PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_SET_HOFFSET, (int*) (&h));
    763                             if (SOC_FAILURE(rv)) {
    764                                 LOG_ERROR(BSL_LS_SOC_PHY,
    765                                           (BSL_META_U(unit,
    766                                                       "%s\n"), soc_errmsg(rv)));
    767                                 goto exit;
    768                             }
    769                         }
    770                         rv = soc_phyctrl_diag_ctrl(unit, local_ports[j], inst,
    771                                                    PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_SET_VOFFSET, (int *) (&v));/*start measure*/
    772                         if (SOC_FAILURE(rv)) {
    773                             LOG_ERROR(BSL_LS_SOC_PHY,
    774                                       (BSL_META_U(unit,
    775                                                   "%s\n"), soc_errmsg(rv)));
    776                             goto exit;
    777                         }
    778                         rv = soc_port_phy_eyescan_start(unit, local_ports[j], inst, params->counter);
    779                         if (SOC_FAILURE(rv)) {
    780                             LOG_ERROR(BSL_LS_SOC_PHY,
    781                                       (BSL_META_U(unit,
    782                                                   "%s\n"), soc_errmsg(rv)));
    783                             goto exit;
    784                         }
    785 
    786                         if ((flags & SRD_EYESCAN_FLAG_DSC_PRINT)){
    787                             soc_phyctrl_control_set(unit, local_ports[j], SOC_PHY_CONTROL_DUMP, 1);
    788                         }
    789                     }
    790 
    791                     /*clear counters*/
    792                     rv = soc_port_phy_eyescan_counter_clear(unit, local_ports[j], inst, params->counter, &(start_time[j]));
    793                     if (SOC_FAILURE(rv)) {
    794                         LOG_ERROR(BSL_LS_SOC_PHY,
    795                                   (BSL_META_U(unit,
    796                                               "%s\n"), soc_errmsg(rv)));
    797                         goto exit;
    798                     }
    799                 }
    800                 sal_usleep(params->sample_time*1000);
    801 
    802                 for (j = 0; j < nof_ports; j++) {
    803 
    804                     /*if serdes is unlock continue*/
    805                     if (local_ports[j] == -1) continue;
    806 
    807                     /*stop measure*/
    808                     rv = soc_port_phy_eyescan_stop(unit, local_ports[j], inst, params->counter, &end_time);
    809                     if (SOC_FAILURE(rv)) {
    810                         LOG_ERROR(BSL_LS_SOC_PHY,
    811                                   (BSL_META_U(unit,
    812                                               "%s\n"), soc_errmsg(rv)));
    813                         goto exit;
    814                     }
    815                     rv = soc_port_phy_eyescan_counter_get(unit, local_ports[j], inst,  params->counter, &err_count);
    816                     if (SOC_FAILURE(rv)) {
    817                         LOG_ERROR(BSL_LS_SOC_PHY,
    818                                   (BSL_META_U(unit,
    819                                               "%s\n"), soc_errmsg(rv)));
    820                         goto exit;
    821                     }
    822 
    823                     time_before = results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX];
    824 
    825                     if(end_time > start_time[j]) {
    826                         results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] += (end_time - start_time[j])/1000;
    827                     } else {
    828                         results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] += ((SAL_USECS_TIMESTAMP_ROLLOVER - start_time[j]) + end_time)/1000;
    829                     }
    830                     results[j].error_count[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] += (err_count);
    831 
    832                     if (results[j].error_count[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] < params->error_threshold) {
    833                         under_threshold++;
    834                     }
    835 
    836                     if (flags & SRD_EYESCAN_FLAG_DSC_PRINT) {
    837                          LOG_CLI((BSL_META_U(unit,
    838                                              "Added %d errors in %d miliseconds for port %d\n"), err_count, (results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] - time_before), local_ports[j]));
    839                     }
    840 #if 0
    841                     port = local_ports[j];
    842                     index = j;
    843 #endif
    844                 }
    845 
    846                 first_run = 0;
    847                 if (params->counter == socPortPhyEyescanCounterRelativePhy) {
    848                     break;
    849                 }
    850             }
    851             if (first_run) {
    852                 for (j = 0; j < nof_ports; j++) {
    853                     results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] = (params->sample_time-1);
    854                 }
    855             }
    856 
    857             if ((params->counter != socPortPhyEyescanCounterRelativePhy) && (desired_time < params->time_upper_bound)) {
    858                 params->sample_time = total_time;
    859             }
    860 
    861             if ((params->sample_time < params->time_upper_bound) && (total_time >= params->time_upper_bound)) {
    862                 params->sample_time = params->time_upper_bound;
    863             }
    864         }
    865 
    866         if(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY) {
    867             break;
    868         }
    869     }
    870 
    871     /*highest number of errors for unlock serdes*/
    872      for (j = 0; j < nof_ports; j++) {
    873          /*if serdes is unlock continue*/
    874          if (local_ports[j] != -1) continue;
    875 
    876          LOG_CLI((BSL_META_U(unit,
    877                              "ERROR: link %d is unlock.\n"), ports[j]));
    878         /*error results*/
    879         for(h = params->bounds.horizontal_min ; h <= params->bounds.horizontal_max ; h++) {
    880             if(h % params->sample_resolution != 0) {
    881                 if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)){
    882                     continue;
    883                 }
    884             }
    885             for (v = params->bounds.vertical_min ; v <= params->bounds.vertical_max ; v++) {
    886                 if(v % params->sample_resolution != 0) {
    887                     continue;
    888                 }
    889 
    890                 results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] = 0;
    891                 results[j].error_count[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] = 0;
    892 
    893             }
    894         }
    895      }
    896 
    897 exit:
    898     if (start_time != NULL) {
    899         sal_free(start_time);
    900     }
    901 
    902     if (v_init_offset) {
    903 
    904         /*disable eyescan mode*/
    905         for (j = 0; j < nof_ports; j++) {
    906             /*if serdes is unlock continue*/
    907             if (local_ports != NULL) {
    908                 if (local_ports[j] == -1) continue;
    909 
    910                 soc_port_phy_eyescan_enable(unit, inst, flags, local_ports[j], params->counter, 0, &(v_init_offset[j]));
    911             }
    912         }
    913         if (v_init_offset != NULL) {
    914             sal_free(v_init_offset);
    915         }
    916     }
    917 
    918     /* check if the lane num needs to be recovered */
    919     if (lane_num != NULL) {
    920         phy_ctrl_t *pc;               
    921         for (j = 0 ; j < nof_ports ; j++) {
    922             if (local_ports != NULL) {
    923                 if (local_ports[j] == -1) continue;
    924                 pc = INT_PHY_SW_STATE(unit, local_ports[j]);
    925                 if (local_lane_num != NULL) {
    926                     pc->lane_num = local_lane_num[j];
    927                 }
    928             }
    929         }
    930     }
    931 
    932     if (local_ports != NULL) {
    933         sal_free(local_ports);
    934     }
    935     if (local_lane_num != NULL) {
    936         sal_free(local_lane_num);
    937     }
    938 
    939     return rv;
    940 }
    941 
    942 #ifdef PHYMOD_SUPPORT
    943 
    944 /* 
    945  * The term "legacy mode" here is referred to the code before TSCE/TSCF projects.
    946  * TSCE/TSCE introduces the capability to use uC to assist eyescan, ber and etc.
    947  * The legacy mode/method used pd_diag_ctrl channel.  However, a phy glue logic 
    948  * could build the phy_diag_ctrl channel on the surface as well, but still 
    949  * deploy the uC assist deep down.
    950  */ 
    951 int is_eyescan_algorithm_legacy_mode(int unit, uint32 nof_ports, soc_port_t* ports, uint32 inst)
    952 {
    953     int legacy;
    954     phy_ctrl_t *pc;
    955     soc_phymod_ctrl_t         *pmc;
    956     soc_phymod_phy_t          *phy;
    957 
    958     legacy = 1;   /* 1 means to use phy_diag_ctrl legacy mode/method */
    959 
    960     if (!nof_ports) return (legacy);
    961 
    962     if (!ext_phy_ctrl[unit]) {
    963         return (0);
    964     }
    965     /* external phy */
    966     if (PHY_DIAG_INST_DEV(inst) == PHY_DIAG_DEV_EXT) {
    967         pc = EXT_PHY_SW_STATE(unit, ports[0]);
    968         
    969         if (soc_feature(unit, soc_feature_portmod)) { 
    970             /* some phymod device could use phy_diag mode
    971              * currently a NULL under portmod is assigned for phymod
    972              * and phymod is assumed to be all non phy_diag mode
    973              */
    974             if (!pc) {
    975                 return (0);
    976             }
    977             if (!pc->pd) {
    978                 return (0);
    979             }
    980         } else {
    981             if (!pc || !pc->pd) {
    982                 LOG_ERROR(BSL_LS_SOC_PHY,
    983                           (BSL_META_U(unit,
    984                                       "Ext Phy ID0: non portmod mode has NULL extPHY\n")));
    985                 return (0);
    986             }
    987         }
    988         /* if pc is available, use the following check to figure     
    989          * out legacy mode or not
    990          */                                   
    991         LOG_INFO(BSL_LS_SOC_PHY,
    992                   (BSL_META_U(unit,
    993                               "Ext Phy ID0: 0x%X, Phy ID1: 0x%X Phy Model: 0x%X \n"),
    994                    pc->phy_id0, pc->phy_id1, pc->phy_model));
    995 
    996         /* Note:
    997          *  we should phase out the following code methods soon
    998          *  for accuracy and portability.   
    999          */
   1000         /* Checking id for furia */
   1001         if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5230)) {
   1002             legacy = 0;
   1003         }
   1004         /* Checking id for QSGMIIE and viper*/
   1005         if ((pc->phy_id0 == 0x0143) && (pc->phy_id1 == 0xbff0)) {
   1006             legacy = 0;
   1007         }
   1008         /* Checking id for Qudra28 */
   1009         if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5250)) {
   1010             legacy = 0;
   1011         }
   1012         /* Checking id for Sesto */
   1013         if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5290)) {
   1014             legacy = 0;
   1015         }
   1016         if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x52b0)) {
   1017             legacy = 0;
   1018         }
   1019         /* Checking id for PHY8806X */
   1020         if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x52c0)) {
   1021             legacy = 0;
   1022         }
   1023     } else {
   1024         /*
   1025          * internal phy
   1026          */
   1027         if (soc_feature(unit, soc_feature_portmod)) { 
   1028             /* Under portmod, internal phymod is assumed to be non phy_diag_ctrl mode.
   1029              * But the assumption could be wrong one day.
   1030              */
   1031             return 0 ; 
   1032         } else {
   1033             pc = INT_PHY_SW_STATE(unit, ports[0]);
   1034             if (!pc) {
   1035                 return(0);
   1036             }            
   1037             LOG_INFO(BSL_LS_SOC_PHY,
   1038                       (BSL_META_U(unit,
   1039                                   "Int Phy ID0: 0x%X, Phy ID1: 0x%X Phy Model: 0x%X \n"),
   1040                        pc->phy_id0, pc->phy_id1, pc->phy_model));
   1041 
   1042             /* Note:
   1043              *    we should phase out the following code methods soon
   1044              *    for accuracy and portability.
   1045              */
   1046             if ((pc->phy_id0 == 0x143) && (pc->phy_id1 == 0xbff0) && (pc->phy_model == 0x3f)) {
   1047                 return (legacy);
   1048             }
   1049             /* Checking id for TSC/WC family; check phymod object for TSCE/TSCF */
   1050             if ((pc->phy_id0 == 0x600d) && (pc->phy_id1 == 0x8770)) {
   1051                 pmc = &pc->phymod_ctrl;
   1052                 if (pmc != NULL) {
   1053                     phy = pmc->phy[0];
   1054                     if (phy != NULL) {
   1055                         legacy = 0 ;
   1056                     }
   1057                 }
   1058             }
   1059         }
   1060     }
   1061     return (legacy);
   1062 }
   1063 
   1064 /* 
   1065    Some phyctrl_diag mode is using uC assist.  Then it doesn't need to use the reporting code 
   1066    from the legacy method. 
   1067  */
   1068 int is_eyescan_algorithm_legacy_rpt_mode(int unit, uint32 nof_ports, soc_port_t* ports, uint32 inst) 
   1069 {
   1070     /* need to expand more cases  */
   1071     return is_eyescan_algorithm_legacy_mode(unit, nof_ports, ports, inst) ;
   1072 }
   1073 
   1074 const phymod_phy_access_t* _get_phymod_phy_access(soc_phymod_ctrl_t *pmc, int phy_idx)
   1075 {
   1076     if (!pmc) return (NULL); 
   1077     if (!pmc->phy[phy_idx]) return (NULL);
   1078     return(&pmc->phy[phy_idx]->pm_phy);
   1079 }
   1080 
   1081 /* 
   1082    To find out what is the first lane position (0, 1, ...) 
   1083    for a given port.   Retunr the lane postion value or -1.
   1084 */
   1085 int first_lane_mask_position(uint32 lane_mask) {
   1086     int lane_pos =0, found=0 ;
   1087 
   1088     while(lane_mask) {
   1089         if(lane_mask & 0x1) {
   1090             found = 1 ; 
   1091             break ;
   1092         }
   1093         lane_pos  +=1 ;
   1094         lane_mask >>= 1 ;
   1095     }
   1096     if(found) { return lane_pos ; }
   1097     else      { return -1 ; }
   1098 }
   1099 
   1100 STATIC int
   1101 _soc_port_generate_phy_array(
   1102     int                             unit,
   1103     uint32                          inst,       /* phy instance containing phy number and interface */
   1104     uint32                          nof_ports,
   1105     soc_port_t*                     ports,
   1106     int*                            lane_num,   /* array of lane index offset 0, 1, ... */
   1107     int                             lane,       /* secondray lane offset indication */
   1108     int                             check_pmd_lock,
   1109     int                             phy_acc_max_length,
   1110     phymod_phy_access_t*            phy_acc,    /* out */
   1111     int*                            port_ids,   /* out */
   1112     int*                            line_rates, /* out, optional */
   1113     int*                            phy_acc_length /* out */)
   1114 
   1115 {
   1116     int                 phy_acc_count, j, idx;
   1117     int                 local_lane_num, rv;
   1118     soc_phymod_ctrl_t   *pmc = NULL;
   1119     phy_ctrl_t          *pc;
   1120     const phymod_phy_access_t *pa;
   1121     uint32 locked;
   1122     int    lane_pos=0;
   1123     int    is_legacy = 0;
   1124 
   1125     /* Generate phys array */
   1126     phy_acc_count = 0;
   1127     for(j = 0 ; j < nof_ports ; j++) {
   1128 
   1129         if(!SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), ports[j])){
   1130             LOG_ERROR(BSL_LS_SOC_PHY,
   1131                   (BSL_META_U(unit, "Port %d can't run eyescan \n"), ports[j]));
   1132             continue;
   1133         }
   1134         if ((j == 0) && (PHY_DIAG_INST_DEV(inst) == PHY_DIAG_DEV_EXT)) {
   1135             if ((ext_phy_ctrl[unit]) && (pc = EXT_PHY_SW_STATE(unit, ports[0])) && (pc->pd)) {
   1136                 is_legacy = 1;
   1137             }
   1138         }
   1139 
   1140         if ((soc_feature(unit, soc_feature_portmod)) && !is_legacy) {
   1141 #ifdef PORTMOD_SUPPORT
   1142     uint32  saved_lane_mask[3];
   1143     int     i; 
   1144             portmod_access_get_params_t params;
   1145             phymod_phy_access_t access[PHYMOD_CONFIG_MAX_CORES_PER_PORT];
   1146             int nof_phys, dev, intf;
   1147             portmod_port_interface_config_t if_config;
   1148 
   1149             intf = PHY_DIAG_INTF_DFLT;
   1150             portmod_access_get_params_t_init(unit, &params);
   1151 
   1152             params.lane = lane_num ? lane_num[j] : lane;
   1153             params.phyn = 0; /* internal phy */
   1154             params.apply_lane_mask = 1; 
   1155 
   1156             dev = PHY_DIAG_INST_DEV(inst);
   1157             if (dev == PHY_DIAG_DEV_EXT) {
   1158                 params.phyn = 1; /* external phy */
   1159                 intf = PHY_DIAG_INST_INTF(inst);
   1160                 if(intf == PHY_DIAG_INTF_SYS) {
   1161                     params.sys_side = PORTMOD_SIDE_SYSTEM;
   1162                 } else {
   1163                     params.sys_side = PORTMOD_SIDE_LINE;
   1164                 }
   1165             }
   1166             
   1167             /* it picks one lane or all lane mask based on params.lane */
   1168             rv = portmod_port_phy_lane_access_get(unit, ports[j], &params, PHYMOD_CONFIG_MAX_CORES_PER_PORT, 
   1169                                                   access, &nof_phys, NULL);
   1170             SOC_IF_ERROR_RETURN(rv);
   1171 
   1172             
   1173             if ( nof_phys == 3 ){
   1174                 for(i=0; i < nof_phys; i++) {
   1175                     saved_lane_mask[i] = access[i].access.lane_mask;
   1176                     access[i].access.lane_mask = 0; /* need this to do compare. */
   1177                 }
   1178 
   1179                 if( !sal_memcmp( &access[0],&access[1], sizeof(phymod_phy_access_t)) &&
   1180                     !sal_memcmp( &access[0],&access[2], sizeof(phymod_phy_access_t))){
   1181                     access[0].access.lane_mask = ( saved_lane_mask[0]| saved_lane_mask[1]| saved_lane_mask[2]);
   1182                     phymod_access_t_init(&access[1].access);
   1183                     phymod_access_t_init(&access[2].access);
   1184                     /* cli_out("Consolidating entries.\n");*/ 
   1185                     nof_phys = 1;
   1186                 } else {
   1187                     /* restore lane mask */
   1188                     for(i=0; i < nof_phys; i++) {
   1189                         access[i].access.lane_mask = saved_lane_mask[i];
   1190                     }
   1191                 }
   1192             }
   1193 
   1194             for(idx = 0 ; idx < nof_phys ; idx++) {
   1195                 pa = &(access[idx]);
   1196 
   1197                 if(check_pmd_lock) {
   1198                     rv = phymod_phy_rx_pmd_locked_get(pa, &locked);
   1199                     SOC_IF_ERROR_RETURN(rv);
   1200 
   1201                     if(!locked) {
   1202                         if(nof_phys > 1) {
   1203                             LOG_WARN(BSL_LS_SOC_PHY,
   1204                                      (BSL_META_U(unit, "p=%d phy idx=%0d is skipped, phy rx isn't locked \n"), ports[j], idx));
   1205                         } else {
   1206                             LOG_WARN(BSL_LS_SOC_PHY,
   1207                                      (BSL_META_U(unit, "Port %d is skipped, Phy RX isn't locked \n"), ports[j]));
   1208                         }
   1209                         continue;
   1210                     } 
   1211                 }
   1212 
   1213                 if(phy_acc_count >= phy_acc_max_length) {
   1214                     LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit,
   1215                                           "ERROR: No space left for phy_acc\n")));
   1216                     return SOC_E_INTERNAL;
   1217                 }
   1218 
   1219                 if(line_rates) {
   1220                     rv = portmod_port_interface_config_get(unit, ports[j], &if_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY);
   1221                     SOC_IF_ERROR_RETURN(rv);
   1222                     line_rates[phy_acc_count] = if_config.speed;
   1223                 }
   1224 
   1225                 sal_memcpy(&(phy_acc[phy_acc_count]), pa, sizeof(phymod_phy_access_t));
   1226                 port_ids[phy_acc_count] = ports[j] ;
   1227                 phy_acc_count++;
   1228             }
   1229 
   1230 #endif /*PORTMOD_SUPPORT*/
   1231         } else {
   1232             int intf = PHY_DIAG_INTF_DFLT;
   1233             int dev = PHY_DIAG_INST_DEV(inst);
   1234             if (dev == PHY_DIAG_DEV_EXT) {
   1235                 pc = EXT_PHY_SW_STATE(unit, ports[j]);
   1236             } else {
   1237                 pc = INT_PHY_SW_STATE(unit, ports[j]);
   1238             }
   1239 
   1240             if (pc == NULL) {
   1241                 LOG_ERROR(BSL_LS_SOC_PHY,
   1242                           (BSL_META_U(unit, "Err: port %d, pc is NULL \n"), ports[j]));
   1243                 continue;
   1244             }
   1245 
   1246             if (dev == PHY_DIAG_DEV_EXT) {
   1247                 intf = PHY_DIAG_INST_INTF(inst);
   1248                 if (intf == PHY_DIAG_INTF_SYS) {
   1249                     pc->flags |= PHYCTRL_SYS_SIDE_CTRL;
   1250                 } else {
   1251                     pc->flags &= ~PHYCTRL_SYS_SIDE_CTRL;
   1252                 }
   1253             }
   1254 
   1255             pmc = &pc->phymod_ctrl;
   1256             if (pmc == NULL) {
   1257                 LOG_ERROR(BSL_LS_SOC_PHY,
   1258                           (BSL_META_U(unit, "Err: port %d, pmc is NULL \n"), ports[j]));
   1259                 continue;
   1260             }
   1261 
   1262             local_lane_num = pc->lane_num;  /* pc->lane_num used to indicate which lane to focus on */
   1263             if (lane_num != NULL) {         /* in the leagcy driver                                 */
   1264                 pc->lane_num = lane_num[j];
   1265             }
   1266 #ifdef INCLUDE_FCMAP
   1267             else  if (pc->fcmap_enable && (intf == PHY_DIAG_INTF_LINE)) {
   1268                     pc->lane_num = 0;
   1269             }
   1270 #endif
   1271 
   1272             for (idx = 0; idx < pmc->num_phys; idx++) {
   1273                 pa = _get_phymod_phy_access(pmc, idx);
   1274                 if (!pa) {
   1275                     if(pmc->num_phys>1) {
   1276                         LOG_ERROR(BSL_LS_SOC_PHY,
   1277                               (BSL_META_U(unit,
   1278                                           "ERROR: p=%0d phymod idx=%0d access is NULL\n"), ports[j], idx));
   1279                     } else {
   1280                         LOG_ERROR(BSL_LS_SOC_PHY,
   1281                                   (BSL_META_U(unit,
   1282                                           "ERROR: phymod Access on port%d is NULL\n"), ports[j]));
   1283                     }
   1284                     continue;
   1285                 }
   1286 
   1287                 if(check_pmd_lock) {
   1288                     rv = phymod_phy_rx_pmd_locked_get(pa, &locked);
   1289                     SOC_IF_ERROR_RETURN(rv);
   1290 
   1291                     if(!locked) {
   1292                         if(pmc->num_phys>1) {
   1293                             LOG_WARN(BSL_LS_SOC_PHY,
   1294                                      (BSL_META_U(unit, "p=%d phy idx=%0d is skipped, phy rx isn't locked \n"), ports[j], idx));
   1295                         } else {
   1296                             LOG_WARN(BSL_LS_SOC_PHY,
   1297                                      (BSL_META_U(unit, "Port %d is skipped, Phy RX isn't locked \n"), ports[j]));
   1298                         }
   1299                         continue; 
   1300                     }
   1301                 }
   1302 
   1303                 if(phy_acc_count >= phy_acc_max_length) {
   1304                     LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit,
   1305                                           "ERROR: No space left for phy_acc\n")));
   1306                     pc->lane_num = local_lane_num;
   1307                     return SOC_E_INTERNAL;
   1308                 }
   1309 
   1310                 if(line_rates) {
   1311                     rv = soc_phyctrl_speed_get(unit, ports[j], &(line_rates[phy_acc_count]));
   1312                     if(SOC_FAILURE(rv)) {
   1313                         LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit,
   1314                                           "ERROR: Failed to retrive speed for port %d \n"), ports[j]));
   1315                         pc->lane_num = local_lane_num;
   1316                         return SOC_E_INTERNAL;
   1317                     }
   1318                 }
   1319                 port_ids[phy_acc_count] = ports[j] ;
   1320                 sal_memcpy(&(phy_acc[phy_acc_count]), pa, sizeof(phymod_phy_access_t));
   1321                 /* fix the lane mask by lane_num */
   1322                 if(lane_num != NULL) {
   1323                     lane_pos = first_lane_mask_position(phy_acc[phy_acc_count].access.lane_mask) ;
   1324                     if(lane_pos>=0) {
   1325                         phy_acc[phy_acc_count].access.lane_mask &= (1<< (lane_num[j]+lane_pos)) ;
   1326                     }
   1327                     /* lane_mask exception is handled later in the functions call this code */
   1328                 }
   1329 #ifdef INCLUDE_FCMAP
   1330                 else  if (pc->fcmap_enable && (intf == PHY_DIAG_INTF_LINE)) {
   1331                     lane_pos = first_lane_mask_position(phy_acc[phy_acc_count].access.lane_mask) ;
   1332                     if(lane_pos>=0) {
   1333                         phy_acc[phy_acc_count].access.lane_mask &= (1<< lane_pos) ;
   1334                     }
   1335                 }
   1336 #endif
   1337                 phy_acc_count++;
   1338             }
   1339             pc->lane_num = local_lane_num;
   1340         }  /* soc_feature_portmod else */
   1341     }
   1342 
   1343     *phy_acc_length = phy_acc_count;
   1344     return SOC_E_NONE;
   1345 }
   1346 
   1347 int _soc_port_phy_eyescan_run_lowber( 
   1348     int                             unit, 
   1349     uint32                          inst,    /* phy instance containing phy number and interface */
   1350     int                             flags, 
   1351     soc_port_phy_eyescan_params_t*  params, 
   1352     uint32                          nof_ports,
   1353     soc_port_t*                     ports,
   1354     int*                            lane_num,
   1355     soc_port_phy_eyescan_results_t* results)    /*array of result per port*/
   1356 {
   1357     phymod_phy_access_t* phy_acc = NULL;
   1358     phymod_phy_eyescan_options_t eyescan_options;
   1359     int rv = SOC_E_NONE;
   1360     int* line_rates;
   1361     int* port_ids;
   1362     int array_max_size, phy_acc_length;
   1363     int i;
   1364     /*validate input*/
   1365     if (params == NULL || ports == NULL || results == NULL) {
   1366         LOG_ERROR(BSL_LS_SOC_PHY,
   1367                   (BSL_META_U(unit,
   1368                               "Null parameter\n")));
   1369         return SOC_E_PARAM;
   1370     }
   1371 
   1372     if(params->counter >= socPortPhyEyescanNofCounters || params->counter < 0) {
   1373         LOG_ERROR(BSL_LS_SOC_PHY,
   1374                   (BSL_META_U(unit,
   1375                               "Counter %d isn't supported\n"), params->counter));
   1376         return SOC_E_PARAM;
   1377     }
   1378 
   1379 
   1380     /* default_sample_time = params->sample_time; */
   1381     eyescan_options.timeout_in_milliseconds = params->sample_time;
   1382     eyescan_options.horz_max = params->bounds.horizontal_max; 
   1383     eyescan_options.horz_min = params->bounds.horizontal_min;
   1384     eyescan_options.hstep = params->sample_resolution;
   1385     eyescan_options.vert_max = params->bounds.vertical_max;
   1386     eyescan_options.vert_min = params->bounds.vertical_min;
   1387     eyescan_options.vstep = params->sample_resolution;
   1388     eyescan_options.mode = (params->type == 3)? 1 << 2: 0; /*Mode should be DIAG_BER_INTR for type3*/
   1389     /* following param are used in BER projection */
   1390     eyescan_options.ber_proj_scan_mode = params->ber_proj_scan_mode;
   1391     eyescan_options.ber_proj_timer_cnt = params->ber_proj_timer_cnt;
   1392     eyescan_options.ber_proj_err_cnt = params->ber_proj_err_cnt;
   1393  
   1394     /* Allocate Mem */
   1395     array_max_size = nof_ports*PHYMOD_CONFIG_MAX_CORES_PER_PORT;
   1396     phy_acc = (phymod_phy_access_t*) sal_alloc(sizeof(phymod_phy_access_t)*array_max_size, "eyescan phymod_phy_access_t");
   1397     line_rates = (int*)sal_alloc(sizeof(int)*array_max_size, "eyescan line rates");
   1398     port_ids   = (int*)sal_alloc(sizeof(int)*array_max_size, "eyescan port ids");
   1399     if(NULL == phy_acc || NULL == line_rates || NULL == port_ids) {
   1400         LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit,
   1401                 "Failed to allocate Memory phy_acc=%d line_rates=%d\n"), phy_acc?1:0, line_rates?1:0));
   1402         rv = SOC_E_MEMORY;
   1403         goto exit;
   1404     }
   1405 
   1406     sal_memset(phy_acc, 0, sizeof(phymod_phy_access_t)*array_max_size);
   1407 
   1408 #if defined(BCM_TOMAHAWK3_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)
   1409     /* For TH3, only front panel ports support this eyescan mode.
   1410      * For front panel ports (PM8x50), we do not need line_rates here.
   1411      * So pass NULL as input for lint_rates.
   1412      */
   1413     if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) {
   1414         rv = _soc_port_generate_phy_array(unit,
   1415                                      inst,
   1416                                      nof_ports,
   1417                                      ports,
   1418                                      lane_num,
   1419                                      -1,
   1420                                      1,
   1421                                      array_max_size,
   1422                                      phy_acc,
   1423                                      port_ids,
   1424                                      NULL,
   1425                                      &phy_acc_length);
   1426     } else
   1427 #endif
   1428     {
   1429         /* Generate phys array */
   1430         rv = _soc_port_generate_phy_array(unit,
   1431                                      inst,
   1432                                      nof_ports,
   1433                                      ports,
   1434                                      lane_num,
   1435                                      -1,
   1436                                      1,
   1437                                      array_max_size,
   1438                                      phy_acc,
   1439                                      port_ids,
   1440                                      line_rates,
   1441                                      &phy_acc_length);
   1442     }
   1443     if(SOC_FAILURE(rv)) {
   1444         goto exit;
   1445     }
   1446 
   1447     for(i=0; i < phy_acc_length; i++) {
   1448         if (phy_acc[i].access.lane_mask == 0) {
   1449             LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit, "Illegal lane_mask of 0 on port %d, aborted.\n"), port_ids[i]));
   1450             goto exit;
   1451         }
   1452     }
   1453 
   1454     /*enable eyescan*/
   1455     if(params->type == 4) {
   1456         rv = phymod_diag_eyescan_run(phy_acc, unit, port_ids, line_rates, phy_acc_length, phymodEyescanModeBERProj, &eyescan_options);
   1457     } else if(params->type >4) {
   1458         LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit,
   1459                   "Eyescan type %d is not supported (type should be <= 4)\n"), params->type));
   1460         goto exit;
   1461     } else {
   1462         rv = phymod_diag_eyescan_run(phy_acc, unit, port_ids, line_rates, phy_acc_length, phymodEyescanModeLowBER, &eyescan_options);
   1463     }
   1464 
   1465 
   1466 exit:
   1467     if(phy_acc != NULL) {
   1468         sal_free(phy_acc);
   1469     }
   1470     if(line_rates != NULL) {
   1471         sal_free(line_rates);
   1472     }
   1473     if(port_ids != NULL) {
   1474         sal_free(port_ids);
   1475     }
   1476     return rv;
   1477 }
   1478 
   1479 /* no eyescan params requred */
   1480 int _soc_port_phy_eyescan_run_fast_uc( 
   1481     int                             unit, 
   1482     uint32                          inst,    /* phy instance containing phy number and interface */
   1483     int                             flags, 
   1484     soc_port_phy_eyescan_params_t*  params, 
   1485     uint32                          nof_ports,
   1486     soc_port_t*                     ports,
   1487     int*                            lane_num,
   1488     soc_port_phy_eyescan_results_t* results)    /*array of result per port*/
   1489 {
   1490     phymod_phy_access_t *phy_acc;
   1491 
   1492     int                 phy_acc_length;
   1493     int                 rv = SOC_E_NONE;
   1494     int i;
   1495     int *port_ids ;
   1496 
   1497     /*validate input*/
   1498     if (!SOC_UNIT_VALID(unit)) {
   1499         LOG_ERROR(BSL_LS_SOC_PHY,
   1500                   (BSL_META_U(unit,
   1501                               "Invalid unit\n")));
   1502         return SOC_E_UNIT;
   1503     }
   1504 
   1505     if (params == NULL || ports == NULL || results == NULL) {
   1506         LOG_ERROR(BSL_LS_SOC_PHY,
   1507                   (BSL_META_U(unit,
   1508                               "Null parameter\n")));
   1509         return SOC_E_PARAM;
   1510     }
   1511 
   1512     /* Allocate Mem */
   1513     phy_acc = (phymod_phy_access_t*) sal_alloc(sizeof(phymod_phy_access_t)*nof_ports*PHYMOD_CONFIG_MAX_CORES_PER_PORT, "eyescan phymod_phy_access_t");
   1514     if(NULL == phy_acc) {
   1515         LOG_ERROR(BSL_LS_SOC_PHY,
   1516                   (BSL_META_U(unit,
   1517                               "Failed to allocate Memory for phy_acc\n")));
   1518         return SOC_E_MEMORY;
   1519     }
   1520     port_ids = (int*)sal_alloc(sizeof(int)*nof_ports*PHYMOD_CONFIG_MAX_CORES_PER_PORT, "eyescan port ids");
   1521     if(NULL == port_ids) {
   1522         sal_free(phy_acc);
   1523         LOG_ERROR(BSL_LS_SOC_PHY,
   1524                   (BSL_META_U(unit,
   1525                               "Failed to allocate Memory for port_ids.\n")));
   1526         return SOC_E_MEMORY;
   1527     }
   1528     sal_memset(phy_acc, 0, sizeof(phymod_phy_access_t)*nof_ports*PHYMOD_CONFIG_MAX_CORES_PER_PORT);
   1529         /* Generate phys array */
   1530 #if defined(BCM_MONTEREY_SUPPORT)
   1531     if ((IS_CPRI_PORT(unit, ports[0])) && SOC_IS_MONTEREY(unit)) {
   1532         rv = _soc_port_generate_phy_array(unit, 
   1533                                      inst, 
   1534                                      nof_ports, 
   1535                                      ports, 
   1536                                      lane_num,
   1537                                      /* lane, */
   1538                                      -1,
   1539                                      0,
   1540                                      nof_ports*PHYMOD_CONFIG_MAX_CORES_PER_PORT,
   1541                                      phy_acc,
   1542                                      port_ids,
   1543                                      NULL,
   1544                                      &phy_acc_length);
   1545     } else
   1546 #endif
   1547     {
   1548         rv = _soc_port_generate_phy_array(unit, 
   1549                                      inst, 
   1550                                      nof_ports, 
   1551                                      ports, 
   1552                                      lane_num,
   1553                                      /* lane, */
   1554                                      -1,
   1555                                      1,
   1556                                      nof_ports*PHYMOD_CONFIG_MAX_CORES_PER_PORT,
   1557                                      phy_acc,
   1558                                      port_ids,
   1559                                      NULL,
   1560                                      &phy_acc_length);
   1561     }
   1562     if(SOC_FAILURE(rv)) {
   1563         goto exit;
   1564     }
   1565     
   1566     for(i=0; i < phy_acc_length; i++ ) {
   1567         if ( phy_acc[i].access.lane_mask == 0 ) {
   1568             LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit, "p=%0d lane_mask=0 causes to abort.\n"), port_ids[i]));
   1569             goto exit;
   1570         }
   1571     }
   1572 
   1573     /* Run fast eyescan: no eyescan options required */
   1574     rv = phymod_diag_eyescan_run(phy_acc, unit, port_ids, NULL, phy_acc_length, phymodEyescanModeFast, NULL);
   1575 exit:
   1576     if(phy_acc != NULL) {
   1577         sal_free(phy_acc);
   1578     }
   1579     if(port_ids != NULL) {
   1580         sal_free(port_ids);
   1581     }
   1582     return rv;
   1583 }
   1584 #endif
   1585 
   1586 
   1587 /* Please consult thephymod team firt before modify this function or functions called inside */
   1588 /* this function.  each port group in the function argument would be required to expect the  */
   1589 /* same phy_diag call mode or phymod call mode.                                              */
   1590 
   1591 int soc_port_phy_eyescan_run ( 
   1592     int unit, 
   1593     uint32 inst,            /* phy instance containing phy number and interface */
   1594     int flags, 
   1595     soc_port_phy_eyescan_params_t* params, 
   1596     uint32 nof_ports,
   1597     soc_port_t* ports,
   1598     int* lane_num,
   1599     soc_port_phy_eyescan_results_t* results /*array of result per port*/) 
   1600 {
   1601 #ifdef PHYMOD_SUPPORT
   1602 
   1603     if (is_eyescan_algorithm_legacy_mode(unit, nof_ports, ports,inst)) {
   1604         return _soc_port_phy_eyescan_run(unit, inst, flags, params, nof_ports, 
   1605                                        ports, lane_num, results);
   1606     } else {
   1607         int rv, i;
   1608         int *saved_intf = NULL;
   1609         phy_ctrl_t *pc = NULL;
   1610         int is_legacy = 0;
   1611 
   1612         if (PHY_DIAG_INST_DEV(inst) == PHY_DIAG_DEV_EXT) {
   1613             if ((ext_phy_ctrl[unit]) && (pc = EXT_PHY_SW_STATE(unit, ports[0])) && (pc->pd)) {
   1614                 is_legacy = 1;
   1615             }
   1616         }
   1617 
   1618         if ((!soc_feature(unit, soc_feature_portmod)) || (is_legacy)) {
   1619         /* First, Save the PhyCtrl SYS/LINE Flags */
   1620         saved_intf = sal_alloc((nof_ports) * sizeof(int), "eyescan saved intf");
   1621         if (saved_intf != NULL) {
   1622             for(i=0; i<nof_ports; i++ ) {
   1623                 int dev = PHY_DIAG_INST_DEV(inst);
   1624                 if (dev == PHY_DIAG_DEV_EXT) {
   1625                     pc = EXT_PHY_SW_STATE(unit, ports[i]);
   1626                 } else {
   1627                     pc = INT_PHY_SW_STATE(unit, ports[i]);
   1628                 }
   1629                 if(pc == NULL) {
   1630                   LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit, "Can not find port INT/EXT phy\n")));
   1631                   sal_free(saved_intf);
   1632                   return SOC_E_INTERNAL; 
   1633                 }
   1634                 saved_intf[i] = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? 1 : 0;
   1635             }
   1636         } else {
   1637             cli_out("Failed to allocate for saved_intf. Just using teh default");
   1638         }
   1639         }
   1640         if (params->type == 1) {
   1641             rv = _soc_port_phy_eyescan_run_fast_uc(
   1642                                 unit, inst, flags, params, nof_ports, 
   1643                                 ports, lane_num, results);
   1644         } else {
   1645             rv = _soc_port_phy_eyescan_run_lowber(
   1646                                 unit, inst, flags, params, nof_ports, 
   1647                                 ports, lane_num, results);
   1648         }
   1649 
   1650         if ((!soc_feature(unit, soc_feature_portmod)) || (is_legacy)) {
   1651             /* Restore the PhyCtrl SYS/LINE Flags */
   1652             if (saved_intf != NULL) {
   1653                 for(i=0; i<nof_ports; i++ ) {
   1654                     int dev = PHY_DIAG_INST_DEV(inst);
   1655                     if (dev == PHY_DIAG_DEV_EXT) {
   1656                         pc = EXT_PHY_SW_STATE(unit, ports[i]);
   1657                     } else {
   1658                         pc = INT_PHY_SW_STATE(unit, ports[i]);
   1659                     }
   1660                     if (saved_intf[i]) {
   1661                         pc->flags |= PHYCTRL_SYS_SIDE_CTRL;
   1662                     } else {
   1663                         pc->flags &= ~PHYCTRL_SYS_SIDE_CTRL;
   1664                     }
   1665                 }
   1666                 sal_free(saved_intf);
   1667             }
   1668         }
   1669         return rv;
   1670     }
   1671 #else
   1672     return (_soc_port_phy_eyescan_run(unit, inst, flags, params, nof_ports, ports, lane_num, results));
   1673 #endif
   1674 }
   1675 
   1676 
   1677 #ifndef __KERNEL__
   1678 
   1679 #ifdef COMPILER_HAS_DOUBLE
   1680 STATIC COMPILER_DOUBLE 
   1681 _eyescan_util_round_real( COMPILER_DOUBLE original_value, int decimal_places ) 
   1682 {
   1683     
   1684     COMPILER_DOUBLE shift_digits[EYESCAN_UTIL_MAX_ROUND_DIGITS+1] = { 0.0, 10.0, 100.0, 1000.0, 
   1685                           10000.0, 100000.0, 1000000.0, 10000000.0, 100000000.0 };
   1686     COMPILER_DOUBLE shifted;
   1687     COMPILER_DOUBLE rounded;   
   1688     
   1689     if (decimal_places > EYESCAN_UTIL_MAX_ROUND_DIGITS ) {
   1690         LOG_CLI((BSL_META("ERROR: Maximum digits to the right of decimal for rounding "
   1691                           "exceeded. Max %d, requested %d\n"), 
   1692                  EYESCAN_UTIL_MAX_ROUND_DIGITS, decimal_places));
   1693         return 0.0;
   1694     } 
   1695     /* shift to preserve the desired digits to the right of the decimal */   
   1696     shifted = original_value * shift_digits[decimal_places];
   1697 
   1698     /* convert to integer and back to COMPILER_DOUBLE to truncate undesired precision */
   1699     shifted = (COMPILER_DOUBLE)(floor(shifted+0.5));
   1700 
   1701     /* shift back to place decimal point correctly */   
   1702     rounded = shifted / shift_digits[decimal_places];
   1703     return rounded;
   1704 }
   1705 #endif /* COMPILER HAS DOUBLE */
   1706 
   1707 #ifdef COMPILER_HAS_DOUBLE
   1708 STATIC int  
   1709 _eye_margin_diagram_cal(int unit, EYE_DIAG_INFOt *pInfo, soc_port_phy_eyescan_results_t* results) 
   1710 {
   1711     COMPILER_DOUBLE lbers[MAX_EYE_LOOPS]={0}; /*Internal linear scale sqrt(-log(ber))*/
   1712     COMPILER_DOUBLE margins[MAX_EYE_LOOPS]={0}; /* Eye margin @ each measurement*/
   1713     COMPILER_DOUBLE bers[MAX_EYE_LOOPS]={0}; /* computed bit error rate */
   1714     int delta_n;
   1715     COMPILER_DOUBLE Exy = 0.0;
   1716     COMPILER_DOUBLE Eyy = 0.0;
   1717     COMPILER_DOUBLE Exx = 0.0;
   1718     COMPILER_DOUBLE Ey  = 0.0;
   1719     COMPILER_DOUBLE Ex  = 0.0;
   1720     COMPILER_DOUBLE alpha;
   1721     COMPILER_DOUBLE beta;
   1722     COMPILER_DOUBLE proj_ber;
   1723     COMPILER_DOUBLE proj_margin_12;
   1724     COMPILER_DOUBLE proj_margin_15;
   1725     COMPILER_DOUBLE proj_margin_18;
   1726     COMPILER_DOUBLE sq_err2;
   1727     COMPILER_DOUBLE ierr;
   1728     int beta_max=0;
   1729     int ber_conf_scale[20];
   1730     int start_n;
   1731     int stop_n;
   1732     int low_confidence;
   1733     int loop_index;
   1734     COMPILER_DOUBLE outputs[4];
   1735     COMPILER_DOUBLE eye_unit;
   1736     int n_mono;
   1737     int loop_var, hi_confidence_cnt, veye_cnt, veye_cnt_orig ;
   1738 
   1739     /* Initialize BER confidence scale */
   1740     ber_conf_scale[0] = 3.02;
   1741     ber_conf_scale[1] = 4.7863;
   1742     ber_conf_scale[2] = 3.1623;
   1743     ber_conf_scale[3] = 2.6303;
   1744     ber_conf_scale[4] = 2.2909;
   1745     ber_conf_scale[5] = 2.138;
   1746     ber_conf_scale[6] = 1.9953;
   1747     ber_conf_scale[7] = 1.9055;
   1748     ber_conf_scale[8] = 1.8197;
   1749     ber_conf_scale[9] = 1.7783;
   1750     ber_conf_scale[10] = 1.6982;
   1751     ber_conf_scale[11] = 1.6596;
   1752     ber_conf_scale[12] = 1.6218;
   1753     ber_conf_scale[13] = 1.6218;
   1754     ber_conf_scale[14] = 1.5849;
   1755     ber_conf_scale[15] = 1.5488;
   1756     ber_conf_scale[16] = 1.5488;
   1757     ber_conf_scale[17] = 1.5136;
   1758     ber_conf_scale[18] = 1.5136;
   1759     ber_conf_scale[19] = 1.4791;
   1760     
   1761     LOG_VERBOSE(BSL_LS_SOC_PHY,
   1762                 (BSL_META_U(unit,
   1763                             "first_good_ber_idx: %d, first_small_errcnt_idx: %d\n"),
   1764                  pInfo->first_good_ber_idx,pInfo->first_small_errcnt_idx));
   1765 
   1766     /* re-calculate the range selected for extroplation */
   1767     hi_confidence_cnt = 0;
   1768     veye_cnt          = 0;
   1769     veye_cnt_orig     = pInfo->veye_cnt ;
   1770     for (loop_var = 0; loop_var < pInfo->offset_max; loop_var++) {
   1771         veye_cnt += 1;
   1772         if (pInfo->total_errs[loop_var] >= HI_CONFIDENCE_ERR_CNT) {
   1773             hi_confidence_cnt = hi_confidence_cnt + 1;
   1774         }
   1775         
   1776         if (((hi_confidence_cnt >= 2) && (pInfo->total_errs[loop_var] <
   1777                                           HI_CONFIDENCE_MIN_ERR_CNT)) ||
   1778             ((hi_confidence_cnt <  2) &&
   1779              (pInfo->total_errs[loop_var] < LO_CONFIDENCE_MIN_ERR_CNT)) ) {
   1780             break;  /* exit for loop */
   1781         }
   1782     }
   1783     pInfo->veye_cnt = veye_cnt ;
   1784 
   1785     /* Find the highest data point to use, currently based on at least 1E-8 BER level */
   1786     if (pInfo->first_good_ber_idx == INDEX_UNINITIALIZED) {
   1787         start_n = pInfo->veye_cnt;
   1788     } else {
   1789         start_n = pInfo->first_good_ber_idx;
   1790         if(start_n > pInfo->veye_cnt) {
   1791             start_n =  pInfo->veye_cnt;
   1792         }
   1793     }
   1794     stop_n = pInfo->veye_cnt;
   1795     
   1796     /* Find the lowest data point to use */
   1797     if (pInfo->first_small_errcnt_idx == INDEX_UNINITIALIZED) {
   1798         stop_n = pInfo->veye_cnt;
   1799     } else { 
   1800         stop_n = pInfo->first_small_errcnt_idx;
   1801         if(stop_n > pInfo->veye_cnt) {
   1802             stop_n = pInfo->veye_cnt;
   1803         }
   1804     }
   1805     
   1806     /* determine the number of non-monotonic outliers */
   1807     n_mono = 0;
   1808     for (loop_index = start_n; loop_index < stop_n; loop_index++) {
   1809         if (pInfo->mono_flags[loop_index] == 1) {
   1810             n_mono = n_mono + 1;
   1811         }
   1812     } 
   1813     
   1814     eye_unit = VEYE_UNIT;
   1815     
   1816     for (loop_index = 0; loop_index < pInfo->veye_cnt; loop_index++) {
   1817         if (pInfo->total_errs[loop_index] == 0) {
   1818             bers[loop_index] = (1000.0/(COMPILER_DOUBLE)pInfo->total_elapsed_time[loop_index])/pInfo->rate;
   1819         } else {
   1820             bers[loop_index] = (COMPILER_DOUBLE)(1000.0*(COMPILER_DOUBLE)pInfo->total_errs[loop_index])/
   1821                    (COMPILER_DOUBLE)pInfo->total_elapsed_time[loop_index]/pInfo->rate;
   1822         }
   1823         bers[loop_index] /= 1000;
   1824         margins[loop_index] = (pInfo->offset_max-loop_index)*eye_unit;
   1825     }
   1826     
   1827     if( start_n >= pInfo->veye_cnt ) {        
   1828         outputs[0] = -_eyescan_util_round_real(log(bers[pInfo->veye_cnt-1])/log(10), 1);
   1829         outputs[1] = -100.0;
   1830         outputs[2] = -100.0;
   1831         outputs[3] = -100.0;
   1832         /*  No need to print out the decimal portion of the BER */
   1833         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1834                     (BSL_META_U(unit,
   1835                                 "BER *worse* than 1e-%d\n"),
   1836                      (int)outputs[0]));
   1837         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1838                     (BSL_META_U(unit,
   1839                                 "Negative margin @ 1e-12, 1e-15 & 1e-18\n")));
   1840         results->ext_better = -1;
   1841         results->ext_results_int = (int)outputs[0];
   1842         results->ext_results_remainder = 0;
   1843     } else {
   1844         low_confidence = 0;
   1845         if( (stop_n-start_n - n_mono) < 2 ) {
   1846             /* Code triggered when less than 2 statistically valid extrapolation points */
   1847             LOG_CLI((BSL_META_U(unit,
   1848                                 "\nWARNING: less accurate extrapolation because of less than 2 statistically valid extrapolation points.\n")));
   1849             for( loop_index = stop_n; loop_index < pInfo->veye_cnt; loop_index++ ) {
   1850                 if( pInfo->total_errs[loop_index] < 20 ) {
   1851                     bers[loop_index] = ber_conf_scale[pInfo->total_errs[loop_index]] * bers[loop_index];
   1852                 } else {
   1853                     bers[loop_index] = ber_conf_scale[19] * bers[loop_index];
   1854                 }
   1855                 pInfo->mono_flags[loop_index] = 0;    /* remove flags; or assess again */
   1856             }
   1857             /* Add artificial point at 100% margin to enable interpolation */
   1858             margins[pInfo->veye_cnt] = 100.0;
   1859             bers[pInfo->veye_cnt] = 0.1;
   1860             low_confidence = 1;
   1861             stop_n = pInfo->veye_cnt + 1;
   1862         }
   1863         
   1864         /* Below this point the code assumes statistically valid point available */
   1865         delta_n = stop_n - start_n - n_mono;
   1866         
   1867         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1868                     (BSL_META_U(unit,
   1869                                 "start_n: %d, stop_n: %d, veye: %d, n_mono: %d\n"),
   1870                      start_n,stop_n,pInfo->veye_cnt,n_mono));
   1871         
   1872         /* Find all the correlations */
   1873         for (loop_index = start_n; loop_index < stop_n; loop_index++) {
   1874             lbers[loop_index] = (COMPILER_DOUBLE)sqrt(-log(bers[loop_index]));
   1875         }
   1876         
   1877         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1878                     (BSL_META_U(unit,
   1879                                 "\tstart=%d, stop=%d, low_confidence=%d\n"),
   1880                      start_n, stop_n, low_confidence));
   1881         for (loop_index = start_n; loop_index < stop_n; loop_index++){
   1882             LOG_VERBOSE(BSL_LS_SOC_PHY,
   1883                         (BSL_META_U(unit,
   1884                                     "\ttotal_errs[%d]=0x%08x\n"),
   1885                          loop_index,(int)pInfo->total_errs[loop_index]));
   1886             LOG_VERBOSE(BSL_LS_SOC_PHY,
   1887                         (BSL_META_U(unit,
   1888                                     "\tbers[%d]=%f\n"),
   1889                          loop_index,bers[loop_index]));
   1890             LOG_VERBOSE(BSL_LS_SOC_PHY,
   1891                         (BSL_META_U(unit,
   1892                                     "\tlbers[%d]=%f\n"),
   1893                          loop_index,lbers[loop_index]));
   1894         }
   1895         
   1896         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1897                     (BSL_META_U(unit,
   1898                                 "delta_n = %d\n"),
   1899                      delta_n));
   1900         
   1901         for( loop_index = start_n; loop_index < stop_n; loop_index++ ) {
   1902             if (pInfo->mono_flags[loop_index] == 0) {
   1903                 Exy = Exy + margins[loop_index] * lbers[loop_index]/(COMPILER_DOUBLE)delta_n;
   1904                 Eyy = Eyy + lbers[loop_index]*lbers[loop_index]/(COMPILER_DOUBLE)delta_n;
   1905                 Exx = Exx + margins[loop_index]*margins[loop_index]/(COMPILER_DOUBLE)delta_n;
   1906                 Ey  = Ey + lbers[loop_index]/(COMPILER_DOUBLE)delta_n;
   1907                 Ex  = Ex + margins[loop_index]/(COMPILER_DOUBLE)delta_n;
   1908             }
   1909         }
   1910         
   1911         /* Compute fit slope and offset */
   1912         alpha = (Exy - Ey * Ex)/(Exx - Ex * Ex);
   1913         beta = Ey - Ex * alpha;
   1914         
   1915         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1916                     (BSL_META_U(unit,
   1917                                 "Exy=%f, Eyy=%f, Exx=%f, Ey=%f,Ex=%f alpha=%f, beta=%f\n"),
   1918                      Exy,Eyy,Exx,Ey,Ex,alpha,beta));
   1919         
   1920         /* JPA> Due to the limit of floats, I need to test for a maximum Beta of 9.32 */
   1921         if(beta > 9.32){
   1922             beta_max=1;
   1923             LOG_CLI((BSL_META_U(unit,
   1924                                 "\n\tWARNING: intermediate float variable is maxed out, what this means is:\n")));
   1925             LOG_CLI((BSL_META_U(unit,
   1926                                 "\t\t- The *extrapolated* minimum BER will be reported as 1E-37.\n")));
   1927             LOG_CLI((BSL_META_U(unit,
   1928                                 "\t\t- This may occur if the channel is near ideal (e.g. test loopback)\n")));
   1929             LOG_CLI((BSL_META_U(unit,
   1930                                 "\t\t- While not discrete, reporting an extrapolated BER < 1E-37 is numerically corect, and informative\n\n")));
   1931         }
   1932         
   1933         
   1934         proj_ber = exp(-beta * beta);
   1935         proj_margin_12 = (sqrt(-log(1e-12)) - beta)/alpha;
   1936         proj_margin_15 = (sqrt(-log(1e-15)) - beta)/alpha;
   1937         proj_margin_18 = (sqrt(-log(1e-18)) - beta)/alpha;
   1938         
   1939         sq_err2 = 0;
   1940         for (loop_index = start_n; loop_index < stop_n; loop_index++) {
   1941             ierr = (lbers[loop_index] - (alpha*margins[loop_index] + beta));
   1942             sq_err2 = sq_err2 + ierr*ierr/(COMPILER_DOUBLE)delta_n;
   1943         }
   1944         
   1945         outputs[0] = -_eyescan_util_round_real(log(proj_ber)/log(10),1);
   1946         outputs[1] = _eyescan_util_round_real(proj_margin_18,1);
   1947         outputs[2] = _eyescan_util_round_real(proj_margin_12,1);
   1948         outputs[3] = _eyescan_util_round_real(proj_margin_15,1);
   1949         
   1950         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1951                     (BSL_META_U(unit,
   1952                                 "\t\tlog1e-12=%f, sq=%f\n"),
   1953                      (COMPILER_DOUBLE)log(1e-12),(COMPILER_DOUBLE)sqrt(-log(1e-12))));
   1954         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1955                     (BSL_META_U(unit,
   1956                                 "\t\talpha=%f\n"),
   1957                      alpha));
   1958         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1959                     (BSL_META_U(unit,
   1960                                 "\t\tbeta=%f\n"),
   1961                      beta));
   1962         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1963                     (BSL_META_U(unit,
   1964                                 "\t\tproj_ber=%f\n"),
   1965                      proj_ber));
   1966         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1967                     (BSL_META_U(unit,
   1968                                 "\t\tproj_margin12=%f\n"),
   1969                      proj_margin_12));
   1970         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1971                     (BSL_META_U(unit,
   1972                                 "\t\tproj_margin12=%f\n"),
   1973                      proj_margin_15));
   1974         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1975                     (BSL_META_U(unit,
   1976                                 "\t\tproj_margin18=%f\n"),
   1977                      proj_margin_18));
   1978         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1979                     (BSL_META_U(unit,
   1980                                 "\t\toutputs[0]=%f\n"),
   1981                      outputs[0]));
   1982         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1983                     (BSL_META_U(unit,
   1984                                 "\t\toutputs[1]=%f\n"),
   1985                      outputs[1]));
   1986         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1987                     (BSL_META_U(unit,
   1988                                 "\t\toutputs[2]=%f\n"),
   1989                      outputs[2]));
   1990         
   1991         /* Extrapolated results, low confidence */
   1992         if( low_confidence == 1 ) {
   1993             if(beta_max){
   1994                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   1995                             (BSL_META_U(unit,
   1996                                         "BER(extrapolated) is *better* than 1e-37\n")));
   1997                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   1998                             (BSL_META_U(unit,
   1999                                         "Margin @ 1e-12    is *better* than %f\n"),
   2000                              outputs[2]));
   2001                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2002                             (BSL_META_U(unit,
   2003                                         "Margin @ 1e-15    is *better* than %f\n"),
   2004                              outputs[3]));
   2005                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2006                             (BSL_META_U(unit,
   2007                                         "Margin @ 1e-18    is *better* than %f\n"),
   2008                              outputs[1]));
   2009                 results->ext_better = 1;
   2010                 results->ext_results_int = 37;
   2011                 results->ext_results_remainder = 0;
   2012             }
   2013             else{
   2014                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2015                             (BSL_META_U(unit,
   2016                                         "BER(extrapolated) is *better* than 1e-%f\n"),
   2017                              outputs[0]));
   2018                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2019                             (BSL_META_U(unit,
   2020                                         "Margin @ 1e-12    is *better* than %f\n"),
   2021                              outputs[2]));
   2022                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2023                             (BSL_META_U(unit,
   2024                                         "Margin @ 1e-15    is *better* than %f\n"),
   2025                              outputs[3]));
   2026                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2027                             (BSL_META_U(unit,
   2028                                         "Margin @ 1e-18    is *better* than %f\n"),
   2029                              outputs[1]));
   2030                 results->ext_better = 1;
   2031                 results->ext_results_int = (int)outputs[0];
   2032                 results->ext_results_remainder = (((int)(outputs[0]*100))%100);
   2033             }
   2034             
   2035         /* JPA> Extrapolated results, high confidence */
   2036         } else {           
   2037             if(beta_max){
   2038                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2039                             (BSL_META_U(unit,
   2040                                         "BER(extrapolated) = 1e-37\n")));
   2041                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2042                             (BSL_META_U(unit,
   2043                                         "Margin @ 1e-12    is *better* than %f\n"),
   2044                              outputs[2]));
   2045                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2046                             (BSL_META_U(unit,
   2047                                         "Margin @ 1e-15    is *better* than %f\n"),
   2048                              outputs[3]));
   2049                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2050                             (BSL_META_U(unit,
   2051                                         "Margin @ 1e-18    is *better* than %f\n"),
   2052                              outputs[1]));
   2053                 results->ext_better = 0;
   2054                 results->ext_results_int = 37;
   2055                 results->ext_results_remainder = 0;
   2056             }
   2057             else{
   2058                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2059                             (BSL_META_U(unit,
   2060                                         "BER(extrapolated) = 1e-%4.2f\n"),
   2061                              outputs[0]));
   2062                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2063                             (BSL_META_U(unit,
   2064                                         "Margin @ 1e-12    = %4.2f%%\n"),
   2065                              outputs[2]));
   2066                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2067                             (BSL_META_U(unit,
   2068                                         "Margin @ 1e-15    = %4.2f%%\n"),
   2069                              outputs[3]));
   2070                 LOG_VERBOSE(BSL_LS_SOC_PHY,
   2071                             (BSL_META_U(unit,
   2072                                         "Margin @ 1e-18    = %4.2f%%\n"),
   2073                              outputs[1]));
   2074                 results->ext_better = 0;
   2075                 results->ext_results_int = (int)outputs[0];
   2076                 results->ext_results_remainder = (((int)(outputs[0]*100))%100);
   2077             }
   2078         }
   2079     }
   2080     pInfo->veye_cnt = veye_cnt_orig ;
   2081     return SOC_E_NONE;
   2082 }
   2083 #else    
   2084 STATIC int  
   2085 _eye_margin_diagram_cal(int unit, EYE_DIAG_INFOt *pInfo, soc_port_phy_eyescan_results_t* results) 
   2086 {
   2087     LOG_ERROR(BSL_LS_SOC_PHY,
   2088               (BSL_META_U(unit,
   2089                           "_eye_margin_diagram_cal unavailable with this compiler\n")));
   2090 
   2091     return SOC_E_UNAVAIL;
   2092 }
   2093 #endif
   2094 
   2095 #ifdef COMPILER_HAS_DOUBLE
   2096 STATIC int 
   2097 _eye_margin_ber_cal(int unit, EYE_DIAG_INFOt *pInfo) 
   2098 {
   2099     COMPILER_DOUBLE bers[MAX_EYE_LOOPS]; /* computed bit error rate */
   2100     COMPILER_DOUBLE margins[MAX_EYE_LOOPS]; /* Eye margin @ each measurement*/
   2101     int loop_var;
   2102     COMPILER_DOUBLE eye_unit;
   2103     COMPILER_DOUBLE curr_ber_log;
   2104     COMPILER_DOUBLE prev_ber_log = 0;
   2105     COMPILER_DOUBLE good_ber_level = -7.8;
   2106 
   2107     /* Initialize BER array */
   2108     for (loop_var = 0; loop_var < MAX_EYE_LOOPS; loop_var++) {
   2109         bers[loop_var] = 0.0;
   2110     }
   2111     
   2112     eye_unit = VEYE_UNIT;
   2113     
   2114     LOG_VERBOSE(BSL_LS_SOC_PHY,
   2115                 (BSL_META_U(unit,
   2116                             "\nBER measurement at each offset, num_data_points: %d\n"),
   2117                  pInfo->veye_cnt));
   2118     
   2119     for (loop_var = 0; loop_var < pInfo->veye_cnt; loop_var++) { 
   2120         margins[loop_var] = (pInfo->offset_max-loop_var)*eye_unit;
   2121         LOG_VERBOSE(BSL_LS_SOC_PHY,
   2122                     (BSL_META_U(unit,
   2123                                 "BER measurement at offset: %f\n"),
   2124                      margins[loop_var]));
   2125          
   2126         /* Compute BER */
   2127         if (pInfo->total_errs[loop_var] == 0) { 
   2128             bers[loop_var] = 1000.0/(COMPILER_DOUBLE)pInfo->total_elapsed_time[loop_var]/pInfo->rate;
   2129             bers[loop_var] /= 1000;
   2130             
   2131             LOG_VERBOSE(BSL_LS_SOC_PHY,
   2132                         (BSL_META_U(unit,
   2133                                     "BER @ %04f %% = 1e%04f (%d errors in %d miliseconds)\n"),
   2134                          (COMPILER_DOUBLE)((pInfo->offset_max-loop_var)*eye_unit), 
   2135                          1.0*(log10(bers[loop_var])),
   2136                          pInfo->total_errs[loop_var],
   2137                          pInfo->total_elapsed_time[loop_var]));
   2138         } else { 
   2139             bers[loop_var] = ((COMPILER_DOUBLE)1000.0*((COMPILER_DOUBLE)(pInfo->total_errs[loop_var])))/
   2140                              (COMPILER_DOUBLE)pInfo->total_elapsed_time[loop_var]/pInfo->rate;
   2141             
   2142             /* the rate unit is KHZ, add -3(log10(1/1000)) for actual display  */
   2143             bers[loop_var] /= 1000;
   2144             LOG_VERBOSE(BSL_LS_SOC_PHY,
   2145                         (BSL_META_U(unit,
   2146                                     "BER @ %2.2f%% = 1e%2.2f (%d errors in %d miliseconds)\n"),
   2147                          (pInfo->offset_max-loop_var)*eye_unit,
   2148                          log10(bers[loop_var]),
   2149                          pInfo->total_errs[loop_var],
   2150                          pInfo->total_elapsed_time[loop_var]));
   2151         }
   2152         curr_ber_log = log10(bers[loop_var]);
   2153         
   2154         /* Detect and record nonmonotonic data points */
   2155         if ((loop_var > 0) && (curr_ber_log > prev_ber_log)) {
   2156             pInfo->mono_flags[loop_var] = 1;
   2157         }
   2158         prev_ber_log = curr_ber_log;
   2159         
   2160         LOG_VERBOSE(BSL_LS_SOC_PHY,
   2161                     (BSL_META_U(unit,
   2162                                 "cur_be_log %2.2f\n"),
   2163                      curr_ber_log));
   2164         /* find the first data point with good BER */
   2165         if ((curr_ber_log <= good_ber_level) && 
   2166             (pInfo->first_good_ber_idx == INDEX_UNINITIALIZED)) { 
   2167             LOG_VERBOSE(BSL_LS_SOC_PHY,
   2168                         (BSL_META_U(unit,
   2169                                     "cur_be_log %2.2f, loop_var %d\n"),
   2170                          curr_ber_log,loop_var));
   2171             pInfo->first_good_ber_idx = loop_var;
   2172         }
   2173         if ((pInfo->total_errs[loop_var] < HI_CONFIDENCE_MIN_ERR_CNT) && (pInfo->first_small_errcnt_idx == INDEX_UNINITIALIZED)) {
   2174             /* find the first data point with small error count */
   2175             pInfo->first_small_errcnt_idx = loop_var;
   2176         }
   2177     
   2178     }   /* for loop_var */
   2179 
   2180     return SOC_E_NONE;
   2181 }
   2182 #endif /* COMPILER_HAS_DOUBLE */
   2183 
   2184 int
   2185 soc_port_phy_eyescan_extrapolate(int unit, 
   2186                                  int flags, 
   2187                                  soc_port_phy_eyescan_params_t* params, 
   2188                                  uint32 nof_ports, 
   2189                                  soc_port_t* ports,
   2190                                  soc_port_phy_eyescan_results_t* results)
   2191 {
   2192 #ifdef COMPILER_HAS_DOUBLE
   2193     int i, cnt, vertical_i;
   2194     int rv = SOC_E_NONE, speed;
   2195     EYE_DIAG_INFOt veye_info;
   2196 
   2197     sal_memset(&veye_info, 0, sizeof(EYE_DIAG_INFOt)); 
   2198     /* extrapolate */
   2199     if (!(flags & SRD_EYESCAN_FLAG_AVOID_EXTRAPOLATION) && (flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY) && 
   2200         (params->counter!=socPortPhyEyescanCounterRelativePhy)){
   2201 
   2202         for (i = 0 ; i < nof_ports; i++) {
   2203             rv = soc_phyctrl_speed_get(unit, ports[i], &speed);
   2204             if (SOC_FAILURE(rv)) {
   2205                 LOG_ERROR(BSL_LS_SOC_PHY,
   2206                           (BSL_META_U(unit,
   2207                                       "soc_phyctrl_speed_get failed\n")));
   2208                 return rv;
   2209             }
   2210 
   2211             veye_info.first_good_ber_idx = INDEX_UNINITIALIZED;
   2212             veye_info.first_small_errcnt_idx = INDEX_UNINITIALIZED;
   2213             veye_info.offset_max = params->bounds.vertical_max;
   2214             veye_info.rate = speed*1000;
   2215 
   2216             cnt = 0;
   2217             for (vertical_i = params->bounds.vertical_min ; vertical_i <= params->bounds.vertical_max; vertical_i++){
   2218                 if(vertical_i % params->sample_resolution != 0) {
   2219                    continue;
   2220                 }
   2221                 cnt++;
   2222                 if(cnt == MAX_EYE_LOOPS) {
   2223                     break;
   2224                 }
   2225             }
   2226             veye_info.veye_cnt = cnt; 
   2227             for (vertical_i = params->bounds.vertical_min ; vertical_i <= params->bounds.vertical_max; vertical_i++){
   2228                 cnt--;
   2229                 if(vertical_i % params->sample_resolution != 0) {
   2230                    continue;
   2231                 }
   2232                 veye_info.total_errs[cnt] = results[i].error_count[SOC_PORT_PHY_EYESCAN_H_INDEX][vertical_i + SOC_PORT_PHY_EYESCAN_V_INDEX];
   2233                 veye_info.total_elapsed_time[cnt] = results[i].run_time[SOC_PORT_PHY_EYESCAN_H_INDEX][vertical_i + SOC_PORT_PHY_EYESCAN_V_INDEX];
   2234                 veye_info.mono_flags[cnt] = 0;
   2235             }
   2236             if (veye_info.veye_cnt > MAX_EYE_LOOPS) {
   2237                 rv = SOC_E_PARAM;
   2238                 LOG_ERROR(BSL_LS_SOC_PHY,
   2239                           (BSL_META_U(unit,
   2240                                       "ERROR: veye_cnt > MAX_EYE_LOOPS\n")));
   2241                 return rv;
   2242             }
   2243             _eye_margin_ber_cal(unit, &veye_info);
   2244             _eye_margin_diagram_cal(unit, &veye_info, &(results[i]));
   2245             results[i].ext_done = 1;
   2246         }
   2247     }
   2248 
   2249     return rv;
   2250 #else
   2251     return SOC_E_NONE;
   2252 #endif /* COMPILER_HAS_DOUBLE*/
   2253 }
   2254 
   2255 #else   /* #ifndef __KERNEL__ */
   2256 
   2257 int
   2258 soc_port_phy_eyescan_extrapolate(int unit, 
   2259                                  int flags, 
   2260                                  soc_port_phy_eyescan_params_t* params, 
   2261                                  uint32 nof_ports, 
   2262                                  soc_port_t* ports, 
   2263                                  soc_port_phy_eyescan_results_t* results){
   2264     LOG_CLI((BSL_META_U(unit,
   2265                         "\nExtrapolation is not supported in Linux kernel mode\n")));
   2266 
   2267     return SOC_E_NONE;
   2268 }
   2269 
   2270 #endif /* #ifndef __KERNEL__ */