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

blackhawk_tsc_prbs.c (52461B)


      1 /**************************************************************************************
      2  **************************************************************************************
      3  *  File Name     :  blackhawk_tsc_prbs.c                                                *
      4  *  Created On    :  04 Nov 2015                                                      *
      5  *  Created By    :  Brent Roberts                                                    *
      6  *  Description   :  APIs for Serdes IPs                                              *
      7  *  Revision      :         *
      8  *                                                                                    *
      9  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
     10  * 
     11  * Copyright 2007-2019 Broadcom Inc. All rights reserved.                                                              *
     12  *  No portions of this material may be reproduced in any form without                *
     13  *  the written permission of:                                                        *
     14  *      Broadcom Corporation                                                          *
     15  *      5300 California Avenue                                                        *
     16  *      Irvine, CA  92617                                                             *
     17  *                                                                                    *
     18  *  All information contained in this document is Broadcom Corporation                *
     19  *  company private proprietary, and trade secret.                                    *
     20  */
     21 
     22 /** @file blackhawk_tsc_prbs.c
     23  * Implementation of API PRBS functions
     24  */
     25 #ifdef EXCLUDE_STD_HEADERS
     26 #include <stdio.h>
     27 #include <math.h>
     28 #endif
     29 
     30 #include <phymod/phymod_system.h>
     31 #include "blackhawk_tsc_prbs.h"
     32 #include "blackhawk_tsc_common.h"
     33 #include "blackhawk_tsc_dependencies.h"
     34 #include "blackhawk_tsc_functions.h"
     35 #include "blackhawk_tsc_internal.h"
     36 #include "blackhawk_tsc_internal_error.h"
     37 #include "blackhawk_tsc_select_defns.h"
     38 #include "blackhawk_tsc_access.h"
     39 
     40 #ifdef SERDES_API_FLOATING_POINT
     41 #include <math.h>
     42 #endif
     43 
     44 /******************************/
     45 /*  TX Pattern Generator APIs */
     46 /******************************/
     47 
     48 /* Cofigure shared TX Pattern (Return Val = 0:PASS, 1-6:FAIL (reports 6 possible error scenarios if failed)) */
     49 err_code_t blackhawk_tsc_config_shared_tx_pattern(srds_access_t *sa__, uint8_t patt_length, const char pattern[]) {
     50 
     51   char       patt_final[245] = "";
     52   char       patt_mod[245]   = "", bin[5] = "";
     53   uint8_t    str_len, i, k, j = 0;
     54   uint8_t    offset_len, actual_patt_len = 0, hex = 0;
     55   uint8_t    zero_pad_len    = 0; /* suppress warnings, changed by blackhawk_tsc_INTERNAL_calc_patt_gen_mode_sel() */
     56   uint16_t   patt_gen_wr_val = 0;
     57   uint8_t    mode_sel        = 0; /* suppress warnings, changed by blackhawk_tsc_INTERNAL_calc_patt_gen_mode_sel() */
     58 
     59   EFUN(blackhawk_tsc_INTERNAL_calc_patt_gen_mode_sel(sa__, &mode_sel,&zero_pad_len,patt_length));
     60 
     61   /* Generating the appropriate write value to patt_gen_seq registers */
     62   str_len = (int8_t)USR_STRLEN(pattern);
     63 
     64   if ((str_len > 2) && ((USR_STRNCMP(pattern, "0x", 2)) == 0)) {
     65     /* Hexadecimal Pattern */
     66     for (i=2; i < str_len; i++) {
     67       if (pattern[i] != '_') {
     68         EFUN(blackhawk_tsc_INTERNAL_compute_bin(sa__, pattern[i],bin));
     69         ENULL_STRNCAT(patt_mod, bin, 4);
     70         actual_patt_len = actual_patt_len + 4;
     71         if (actual_patt_len > 240) {
     72           EFUN_PRINTF(("ERROR: Pattern bigger than max pattern length\n"));
     73           return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_PATTERN_BIGGER_THAN_MAXLEN));
     74         }
     75       }
     76     }
     77 
     78     offset_len = (actual_patt_len - patt_length);
     79     if ((offset_len > 3)  || (actual_patt_len < patt_length)) {
     80       EFUN_PRINTF(("ERROR: Pattern length provided does not match the hexadecimal pattern provided\n"));
     81       return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_LEN_MISMATCH));
     82     }
     83     else if (offset_len) {
     84       for (i=0; i < offset_len; i++) {
     85         if (patt_mod[i] != '0') {
     86           EFUN_PRINTF(("ERROR: Pattern length provided does not match the hexadecimal pattern provided\n"));
     87           return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_LEN_MISMATCH));
     88         }
     89       }
     90       for (i=offset_len; i <= actual_patt_len; i++) {
     91         patt_mod[i - offset_len] = patt_mod[i];
     92       }
     93     }
     94   }
     95   else if ((str_len > 1) && ((USR_STRNCMP(pattern, "p", 1)) == 0)) {
     96     /* PAM4 Pattern */
     97     for (i=1; i < str_len; i++) {
     98       if (pattern[i] != '_') {
     99         EFUN(blackhawk_tsc_INTERNAL_pam4_to_bin(sa__, pattern[i],bin));
    100         ENULL_STRNCAT(patt_mod, bin, 2);
    101         actual_patt_len = actual_patt_len + 2;
    102         if (actual_patt_len > 240) {
    103           EFUN_PRINTF(("ERROR: Pattern bigger than max pattern length\n"));
    104           return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_PATTERN_BIGGER_THAN_MAXLEN));
    105         }
    106       }
    107     }
    108 
    109     offset_len = (actual_patt_len - patt_length);
    110     if ((offset_len > 3)  || (actual_patt_len < patt_length)) {
    111       EFUN_PRINTF(("ERROR: Pattern length provided does not match the PAM4 pattern provided\n"));
    112       return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_LEN_MISMATCH));
    113     }
    114     else if (offset_len) {
    115       for (i=0; i < offset_len; i++) {
    116         if (patt_mod[i] != '0') {
    117           EFUN_PRINTF(("ERROR: Pattern length provided does not match the PAM4 pattern provided\n"));
    118           return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_LEN_MISMATCH));
    119         }
    120       }
    121       for (i=offset_len; i <= actual_patt_len; i++) {
    122         patt_mod[i - offset_len] = patt_mod[i];
    123       }
    124     }
    125   }
    126   else {
    127     /* Binary Pattern */
    128     for (i=0; i < str_len; i++) {
    129       if ((pattern[i] == '0') || (pattern[i] == '1')) {
    130         bin[0] = pattern[i];
    131         bin[1] = '\0';
    132         ENULL_STRNCAT(patt_mod, bin, 1);
    133         actual_patt_len++;
    134         if (actual_patt_len > 240) {
    135           EFUN_PRINTF(("ERROR: Pattern bigger than max pattern length\n"));
    136           return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_PATTERN_BIGGER_THAN_MAXLEN));
    137         }
    138       }
    139       else if (pattern[i] != '_') {
    140         EFUN_PRINTF(("ERROR: Invalid input Pattern\n"));
    141         return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_INVALID_PATTERN));
    142       }
    143     }
    144 
    145     if (actual_patt_len != patt_length) {
    146       EFUN_PRINTF(("ERROR: Pattern length provided does not match the binary pattern provided\n"));
    147       return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_LEN_MISMATCH));
    148     }
    149   }
    150 
    151   /* Zero padding upper bits and concatinating patt_mod to form patt_final */
    152   for (i=0; i < zero_pad_len; i++) {
    153     ENULL_STRNCAT(patt_final, "0", 1);
    154     j++;
    155   }
    156   for (i=zero_pad_len; i + patt_length < 241; i = i + patt_length) {
    157     ENULL_STRNCAT(patt_final, patt_mod, patt_length);
    158     j++;
    159   }
    160 
    161   /* EFUN_PRINTF(("\nFinal Pattern = %s\n\n",patt_final));    */
    162 
    163   for (i=0; i < 15; i++) {
    164 
    165     for (j=0; j < 4; j++) {
    166       k = i*16 + j*4;
    167       bin[0] = patt_final[k];
    168       bin[1] = patt_final[k+1];
    169       bin[2] = patt_final[k+2];
    170       bin[3] = patt_final[k+3];
    171       bin[4] = '\0';
    172       EFUN(blackhawk_tsc_INTERNAL_compute_hex(sa__, bin, &hex));
    173       patt_gen_wr_val = ((patt_gen_wr_val << 4) | hex);
    174     }
    175     /* EFUN_PRINTF(("patt_gen_wr_val[%d] = 0x%x\n",(14-i),patt_gen_wr_val));    */
    176 
    177     /* Writing to apprpriate patt_gen_seq Registers */
    178     switch (i) {
    179       case 0:  EFUN(wrc_patt_gen_seq_14(patt_gen_wr_val));
    180                break;
    181       case 1:  EFUN(wrc_patt_gen_seq_13(patt_gen_wr_val));
    182                break;
    183       case 2:  EFUN(wrc_patt_gen_seq_12(patt_gen_wr_val));
    184                break;
    185       case 3:  EFUN(wrc_patt_gen_seq_11(patt_gen_wr_val));
    186                break;
    187       case 4:  EFUN(wrc_patt_gen_seq_10(patt_gen_wr_val));
    188                break;
    189       case 5:  EFUN(wrc_patt_gen_seq_9(patt_gen_wr_val));
    190                break;
    191       case 6:  EFUN(wrc_patt_gen_seq_8(patt_gen_wr_val));
    192                break;
    193       case 7:  EFUN(wrc_patt_gen_seq_7(patt_gen_wr_val));
    194                break;
    195       case 8:  EFUN(wrc_patt_gen_seq_6(patt_gen_wr_val));
    196                break;
    197       case 9:  EFUN(wrc_patt_gen_seq_5(patt_gen_wr_val));
    198                break;
    199       case 10: EFUN(wrc_patt_gen_seq_4(patt_gen_wr_val));
    200                break;
    201       case 11: EFUN(wrc_patt_gen_seq_3(patt_gen_wr_val));
    202                break;
    203       case 12: EFUN(wrc_patt_gen_seq_2(patt_gen_wr_val));
    204                break;
    205       case 13: EFUN(wrc_patt_gen_seq_1(patt_gen_wr_val));
    206                break;
    207       case 14: EFUN(wrc_patt_gen_seq_0(patt_gen_wr_val));
    208                break;
    209       default: EFUN_PRINTF(("ERROR: Invalid write to patt_gen_seq register\n"));
    210                return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_INVALID_SEQ_WRITE));
    211     }
    212   }
    213 
    214   /* Pattern Generator Mode Select */
    215   /* EFUN(wr_patt_gen_mode_sel(mode_sel)); */
    216   /* EFUN_PRINTF(("Pattern gen Mode = %d\n",mode));    */
    217 
    218   /* Enable Fixed pattern Generation */
    219   /* EFUN(wr_patt_gen_en(0x1)); */
    220   return(ERR_CODE_NONE);
    221 }
    222 
    223 
    224 /* Enable/Disable Shared TX pattern generator */
    225 err_code_t blackhawk_tsc_tx_shared_patt_gen_en(srds_access_t *sa__, uint8_t enable, uint8_t patt_length) {
    226   uint8_t zero_pad_len = 0; /* suppress warnings, changed by blackhawk_tsc_INTERNAL_calc_patt_gen_mode_sel() */
    227   uint8_t mode_sel     = 0; /* suppress warnings, changed by blackhawk_tsc_INTERNAL_calc_patt_gen_mode_sel() */
    228 
    229   EFUN(blackhawk_tsc_INTERNAL_calc_patt_gen_mode_sel(sa__, &mode_sel,&zero_pad_len,patt_length));
    230 
    231   if (enable) {
    232     if ((mode_sel < 1) || (mode_sel > 6)) {
    233       return (blackhawk_tsc_error(sa__, ERR_CODE_PATT_GEN_INVALID_MODE_SEL));
    234     }
    235     mode_sel = (12 - mode_sel);
    236     EFUN(wr_patt_gen_start_pos(mode_sel));            /* Start position for pattern */
    237     EFUN(wr_patt_gen_stop_pos(0x0));                  /* Stop position for pattern */
    238     EFUN(wr_patt_gen_en(0x1));                        /* Enable Fixed pattern Generation  */
    239   }
    240   else {
    241     EFUN(wr_patt_gen_en(0x0));                        /* Disable Fixed pattern Generation  */
    242   }
    243   return(ERR_CODE_NONE);
    244 }
    245 
    246 /* Configure JP03B Pattern */
    247 err_code_t blackhawk_tsc_config_tx_jp03b_pattern(srds_access_t *sa__, uint8_t enable) {
    248 
    249   if (enable) {
    250     /* JP03B Pattern - "p0330" => 8'b_0011_1100 or 8'h3C w/o  Gray coding */
    251     /*                         => 8'b_0010_1000 or 8'h28 with Gray coding */
    252     EFUN(wrc_patt_gen_seq_1(0x2800));
    253     EFUN(wr_pam4_precoder_en(0x0));
    254     EFUN(wr_pam4_gray_enc_en(0x0));
    255     EFUN(wr_pam4_tx_jp03b_patt_en(0x1));
    256     EFUN(wr_patt_gen_en(0x1));
    257   }
    258   else {
    259     EFUN(wr_patt_gen_en(0x0));
    260     EFUN(wr_pam4_tx_jp03b_patt_en(0x0));
    261   }
    262   return(ERR_CODE_NONE);
    263 }
    264 
    265 
    266 /* Configure TX Linearity Pattern */
    267 err_code_t blackhawk_tsc_config_tx_linearity_pattern(srds_access_t *sa__, uint8_t enable) {
    268 
    269   if (enable) {
    270     /* Linearity Pattern - "p0123_0303_21" => 20'b_0001_1011_0011_0011_1001 or 20'h1B339 w/o  Gray coding */
    271     /*                                     => 20'b_0001_1110_0010_0010_1101 or 20'h1E22D with Gray coding */
    272     EFUN(wrc_patt_gen_seq_0(0xE22D));
    273     EFUN(wrc_patt_gen_seq_1(0x0001));
    274     EFUN(wr_pam4_precoder_en(0x0));
    275     EFUN(wr_pam4_gray_enc_en(0x0));
    276     EFUN(wr_pam4_tx_jp03b_patt_en(0x0));
    277     EFUN(wr_pam4_tx_linearity_patt_en(0x1));
    278     EFUN(wr_patt_gen_en(0x1));
    279   }
    280   else {
    281     EFUN(wr_patt_gen_en(0x0));
    282     EFUN(wr_pam4_tx_linearity_patt_en(0x0));
    283   }
    284   return(ERR_CODE_NONE);
    285 }
    286 
    287 /**************************************/
    288 /*  PRBS Generator/Checker Functions  */
    289 /**************************************/
    290 
    291 /* Configure PRBS Generator */
    292 err_code_t blackhawk_tsc_config_tx_prbs(srds_access_t *sa__, enum srds_prbs_polynomial_enum prbs_poly_mode, uint8_t prbs_inv) {
    293     uint8_t poly_mode_lsb;
    294     poly_mode_lsb = prbs_poly_mode & 0x7;
    295 
    296   EFUN(wr_prbs_gen_mode_sel((uint8_t)poly_mode_lsb));   /* PRBS Generator mode sel */
    297   EFUN(wr_prbs_gen_mode_sel_msb(prbs_poly_mode > 7));   /* Set MSB for new Poly mode selections */
    298   EFUN(wr_prbs_gen_inv(prbs_inv));                      /* PRBS Invert Enable/Disable */
    299   /* To enable PRBS Generator */
    300   /* EFUN(wr_prbs_gen_en(0x1)); */
    301   return (ERR_CODE_NONE);
    302 }
    303 
    304 err_code_t blackhawk_tsc_get_tx_prbs_config(srds_access_t *sa__, enum srds_prbs_polynomial_enum *prbs_poly_mode, uint8_t *prbs_inv) {
    305     uint8_t val;
    306 
    307   ESTM(val = rd_prbs_gen_mode_sel());                   /* PRBS Generator mode sel */
    308   ESTM(val += (rd_prbs_gen_mode_sel_msb())?8:0);        /* Add the MSB for mode_sel */
    309   *prbs_poly_mode = (enum srds_prbs_polynomial_enum)val;
    310   ESTM(val = rd_prbs_gen_inv());                        /* PRBS Invert Enable/Disable */
    311   *prbs_inv = val;
    312 
    313   return (ERR_CODE_NONE);
    314 }
    315 
    316 /* PRBS Generator Enable/Disable */
    317 err_code_t blackhawk_tsc_tx_prbs_en(srds_access_t *sa__, uint8_t enable) {
    318 
    319   if (enable) {
    320     EFUN(wr_prbs_gen_en(0x1));                          /* Enable PRBS Generator */
    321   }
    322   else {
    323     EFUN(wr_prbs_gen_en(0x0));                          /* Disable PRBS Generator */
    324   }
    325   return (ERR_CODE_NONE);
    326 }
    327 
    328 /* Get PRBS Generator Enable/Disable */
    329 err_code_t blackhawk_tsc_get_tx_prbs_en(srds_access_t *sa__, uint8_t *enable) {
    330 
    331   ESTM(*enable = rd_prbs_gen_en());
    332 
    333   return (ERR_CODE_NONE);
    334 }
    335 
    336 /* PRBS 1-bit error injection */
    337 err_code_t blackhawk_tsc_tx_prbs_err_inject(srds_access_t *sa__, uint8_t enable) {
    338   /* PRBS Error Insert.
    339      0 to 1 transition on this signal will insert single bit error in the MSB bit of the data bus.
    340      Reset value is 0x0.
    341   */
    342   if(enable)
    343     EFUN(wr_prbs_gen_err_ins(0x1));
    344   EFUN(wr_prbs_gen_err_ins(0));
    345   return (ERR_CODE_NONE);
    346 }
    347 
    348 /* Configure PRBS Checker */
    349 err_code_t blackhawk_tsc_config_rx_prbs(srds_access_t *sa__, enum srds_prbs_polynomial_enum prbs_poly_mode, enum srds_prbs_checker_mode_enum prbs_checker_mode, uint8_t prbs_inv) {
    350     uint8_t dig_lpbk = 0;
    351   if (prbs_poly_mode == PRBS_AUTO_DETECT) {
    352     EFUN(wr_prbs_chk_auto_detect_en(0x1));               /* Enable PRBS checker Auto-Detect */
    353     EFUN(wr_prbs_chk_mode(PRBS_INITIAL_SEED_HYSTERESIS));  /* PRBS Checker mode sel (PRBS LOCK state machine select) */
    354   }
    355   else {
    356     uint8_t poly_mode_lsb;
    357     poly_mode_lsb = prbs_poly_mode & 0x7;
    358 
    359     EFUN(wr_prbs_chk_mode_sel((uint8_t)poly_mode_lsb));  /* PRBS Checker Polynomial mode sel  */
    360     EFUN(wr_prbs_chk_mode((uint8_t)prbs_checker_mode));  /* PRBS Checker mode sel (PRBS LOCK state machine select) */
    361     ESTM(dig_lpbk = rd_dig_lpbk_en());
    362     if(dig_lpbk == 0) {
    363         /* Only enable auto mode in non-digital loop-back mode */
    364         EFUN(wr_prbs_chk_en_auto_mode(0x1));                 /* PRBS Checker enable control - rx_dsc_lock & prbs_chk_en */
    365     }
    366     EFUN(wr_prbs_chk_inv(prbs_inv));                     /* PRBS Invert Enable/Disable */
    367     EFUN(wr_prbs_chk_mode_sel_msb(prbs_poly_mode > 7));  /* Set MSB for new Poly mode selections */
    368     EFUN(wr_prbs_chk_auto_detect_en(0x0));               /* Disable PRBS checker Auto-Detect */
    369   }
    370   /* To enable PRBS Checker */
    371   /* EFUN(wr_prbs_chk_en(0x1)); */
    372   return (ERR_CODE_NONE);
    373 }
    374 
    375 /* get PRBS Checker */
    376 err_code_t blackhawk_tsc_get_rx_prbs_config(srds_access_t *sa__, enum srds_prbs_polynomial_enum *prbs_poly_mode, enum srds_prbs_checker_mode_enum *prbs_checker_mode, uint8_t *prbs_inv) {
    377   uint8_t val;
    378 
    379   uint8_t auto_det_en;
    380   ESTM(auto_det_en = rd_prbs_chk_auto_detect_en());       /* PRBS checker Auto-Detect Enable */
    381   if (auto_det_en) {
    382     uint8_t auto_det_lock;
    383     ESTM(auto_det_lock = rd_prbs_chk_auto_detect_lock()); /* PRBS checker Auto-Detect Lock */
    384     if (auto_det_lock) {
    385       ESTM(val = rd_prbs_chk_mode_sel_auto_detect());     /* PRBS Auto-Detect Checker Polynomial mode sel  */
    386       ESTM(val += (rd_prbs_chk_mode_sel_msb_auto_detect())? 8:0);  /* Add the MSB for Auto-Detect mode_sel */
    387       *prbs_poly_mode = (enum srds_prbs_polynomial_enum)val;
    388 
    389       ESTM(val = rd_prbs_chk_mode());                     /* PRBS Checker mode sel (PRBS LOCK state machine select) */
    390       *prbs_checker_mode = (enum srds_prbs_checker_mode_enum)val;
    391       ESTM(val = rd_prbs_chk_inv_auto_detect());          /* PRBS Invert Enable/Disable */
    392       *prbs_inv = val;
    393     }
    394     else {
    395       *prbs_poly_mode = PRBS_UNKNOWN;
    396       *prbs_inv = 0;
    397       ESTM(val = rd_prbs_chk_mode());                     /* PRBS Checker mode sel (PRBS LOCK state machine select) */
    398       *prbs_checker_mode = (enum srds_prbs_checker_mode_enum)val;
    399     }
    400   }
    401   else {
    402     ESTM(val = rd_prbs_chk_mode_sel());                 /* PRBS Checker Polynomial mode sel  */
    403     ESTM(val += (rd_prbs_chk_mode_sel_msb())? 8:0);     /* Add the MSB for mode_sel */
    404     *prbs_poly_mode = (enum srds_prbs_polynomial_enum)val;
    405 
    406     ESTM(val = rd_prbs_chk_mode());                     /* PRBS Checker mode sel (PRBS LOCK state machine select) */
    407     *prbs_checker_mode = (enum srds_prbs_checker_mode_enum)val;
    408     ESTM(val = rd_prbs_chk_inv());                      /* PRBS Invert Enable/Disable */
    409     *prbs_inv = val;
    410   }
    411   return (ERR_CODE_NONE);
    412 }
    413 
    414 /* PRBS Checker Enable/Disable */
    415 err_code_t blackhawk_tsc_rx_prbs_en(srds_access_t *sa__, uint8_t enable) {
    416 
    417     if (enable) {
    418         EFUN(wr_prbs_chk_en(0x1));                          /* Enable PRBS Checker */
    419     }
    420     else {
    421         EFUN(wr_prbs_chk_en(0x0));                          /* Disable PRBS Checker */
    422     }
    423     return (ERR_CODE_NONE);
    424 }
    425 
    426 err_code_t blackhawk_tsc_get_rx_prbs_en(srds_access_t *sa__, uint8_t *enable) {
    427 
    428     ESTM(*enable = rd_prbs_chk_en());
    429     return (ERR_CODE_NONE);
    430 }
    431 
    432 
    433 /* PRBS Checker Lock State */
    434 err_code_t blackhawk_tsc_prbs_chk_lock_state(srds_access_t *sa__, uint8_t *chk_lock) {
    435     if(!chk_lock) {
    436         return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    437     }
    438 
    439     ESTM(*chk_lock = rd_prbs_chk_lock());                  /* PRBS Checker Lock Indication 1 = Locked, 0 = Out of Lock */
    440     return (ERR_CODE_NONE);
    441 }
    442 
    443 /* PRBS Error Count and Lock Lost (bit 31 in lock lost) */
    444 err_code_t blackhawk_tsc_prbs_err_count_ll(srds_access_t *sa__, uint32_t *prbs_err_cnt) {
    445     uint16_t rddata;
    446 
    447     if(!prbs_err_cnt) {
    448         return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    449     }
    450     ESTM(rddata = REG_RD_TLB_RX_PRBS_CHK_ERR_CNT_MSB_STATUS());
    451     *prbs_err_cnt = ((uint32_t) rddata)<<16;
    452     ESTM(*prbs_err_cnt = (*prbs_err_cnt | rd_prbs_chk_err_cnt_lsb()));
    453 
    454 
    455     return (ERR_CODE_NONE);
    456 }
    457 
    458 /* PRBS Error Count State  */
    459 err_code_t blackhawk_tsc_prbs_err_count_state(srds_access_t *sa__, uint32_t *prbs_err_cnt, uint8_t *lock_lost) {
    460     uint8_t dig_lpbk_enable = 0;
    461     uint8_t link_training_enable = 0;
    462     if(!prbs_err_cnt || !lock_lost) {
    463         return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    464     }
    465     EFUN(blackhawk_tsc_prbs_err_count_ll(sa__, prbs_err_cnt));
    466     *lock_lost    = (*prbs_err_cnt >> 31);
    467     *prbs_err_cnt = (*prbs_err_cnt & 0x7FFFFFFF);
    468 
    469     /* Check if Digital Loopback and LinkTrainig both are enabled */
    470     ESTM(dig_lpbk_enable = rd_dig_lpbk_en());
    471 
    472     ESTM(link_training_enable = rd_linktrn_ieee_training_enable());
    473     if(dig_lpbk_enable && link_training_enable) {
    474         EFUN_PRINTF(("WARNING: PRBS Check Lock - Digital Loopback and Link Training both are enabled\n"));
    475     }
    476     return (ERR_CODE_NONE);
    477 }
    478 
    479 /* Save prbs hardware timer config registers */
    480 err_code_t blackhawk_tsc_get_prbs_chk_hw_timer_ctrl(srds_access_t *sa__, struct prbs_chk_hw_timer_ctrl_st * const prbs_chk_hw_timer_ctrl_bak) {
    481     ESTM(prbs_chk_hw_timer_ctrl_bak->prbs_chk_burst_err_cnt_en = rd_prbs_chk_burst_err_cnt_en());
    482     ESTM(prbs_chk_hw_timer_ctrl_bak->prbs_chk_en_timer_mode = rd_prbs_chk_en_timer_mode());
    483     ESTM(prbs_chk_hw_timer_ctrl_bak->prbs_chk_en_timeout = rd_prbs_chk_en_timeout());
    484     return ERR_CODE_NONE;
    485 }
    486 
    487 /* Restore prbs hardware timer config registers */
    488 err_code_t blackhawk_tsc_set_prbs_chk_hw_timer_ctrl(srds_access_t *sa__, struct prbs_chk_hw_timer_ctrl_st const * const prbs_chk_hw_timer_ctrl_bak) {
    489     EFUN(wr_prbs_chk_burst_err_cnt_en(prbs_chk_hw_timer_ctrl_bak->prbs_chk_burst_err_cnt_en));
    490     EFUN(wr_prbs_chk_en_timer_mode(prbs_chk_hw_timer_ctrl_bak->prbs_chk_en_timer_mode));
    491     EFUN(wr_prbs_chk_en_timeout(prbs_chk_hw_timer_ctrl_bak->prbs_chk_en_timeout));
    492     return ERR_CODE_NONE;
    493 }
    494 
    495 /* Configure hardware timer to count prbs errors */
    496 err_code_t blackhawk_tsc_config_prbs_chk_hw_timer(srds_access_t *sa__, uint16_t time_ms, uint16_t *time_ms_adjusted) {
    497 
    498     struct prbs_chk_hw_timer_ctrl_st prbs_chk_hw_timer_ctrl;
    499     USR_MEMSET(&prbs_chk_hw_timer_ctrl, 0, sizeof(struct prbs_chk_hw_timer_ctrl_st));
    500 
    501     EFUN(wr_prbs_chk_burst_err_cnt_en(0));
    502 
    503     /* Figure out timer mode and timer count */
    504     EFUN(blackhawk_tsc_INTERNAL_get_prbs_timeout_count_from_time(time_ms, time_ms_adjusted, &prbs_chk_hw_timer_ctrl));
    505         
    506     EFUN(wr_prbs_chk_en_timer_mode(prbs_chk_hw_timer_ctrl.prbs_chk_en_timer_mode));
    507     EFUN(wr_prbs_chk_en_timeout(prbs_chk_hw_timer_ctrl.prbs_chk_en_timeout));
    508 
    509     return ERR_CODE_NONE;
    510 }
    511 
    512 /* toggle checker enable to start hardware timers and error counters */
    513 err_code_t blackhawk_tsc_prbs_chk_en_toggle(srds_access_t *sa__) {
    514     EFUN(wr_prbs_chk_en(0));
    515     EFUN(wr_prbs_chk_en(1));
    516     return ERR_CODE_NONE;
    517 }
    518 
    519 err_code_t blackhawk_tsc_display_detailed_prbs_state_hdr(void) {
    520     EFUN_PRINTF(("\nPRBS DETAILED DISPLAY :\n"));
    521 
    522 /* Comment out display of PRBS burst error if BLACKHAWK */
    523     EFUN_PRINTF((" LN TX-Mode TX-PRBS-Inv TX-PMD-Inv RX-Mode RX-PRBS-Inv RX-PMD-Inv Lck LL PRBS-Err-Cnt"));
    524     EFUN_PRINTF(("     BER\n"));
    525     return (ERR_CODE_NONE);
    526 }
    527 
    528 const char* blackhawk_tsc_e2s_prbs_mode_enum[17] = {
    529     " PRBS_7",
    530     " PRBS_9",
    531     "PRBS_11",
    532     "PRBS_15",
    533     "PRBS_23",
    534     "PRBS_31",
    535     "PRBS_58",
    536     "PRBS_49",
    537     "PRBS_10",
    538     "PRBS_20",
    539     "PRBS_13",
    540     "  ERR  ",
    541     "  ERR  ",
    542     "  ERR  ",
    543     "  ERR  ",
    544     "  ERR  ",
    545     "UNKNOWN"
    546   };
    547 
    548 err_code_t blackhawk_tsc_display_detailed_prbs_state(srds_access_t *sa__) {
    549     uint32_t err_cnt = 0;
    550     uint8_t lock_lost = 0;
    551     uint8_t enabled;
    552 
    553     ESTM_PRINTF(("  %d ",blackhawk_tsc_get_lane(sa__)));
    554 
    555     ESTM(enabled = rd_prbs_gen_en());
    556     if(enabled) {
    557         enum srds_prbs_polynomial_enum prbs_poly_mode = PRBS_7;
    558         uint8_t prbs_inv = 0;
    559         char *prbs_string;
    560         EFUN(blackhawk_tsc_get_tx_prbs_config(sa__, &prbs_poly_mode, &prbs_inv));
    561         prbs_string = (char *)blackhawk_tsc_e2s_prbs_mode_enum[prbs_poly_mode];
    562         ESTM_PRINTF(("%s",prbs_string));
    563         ESTM_PRINTF(("      %1d     ",prbs_inv));
    564     } else {
    565         EFUN_PRINTF(("  OFF  "));
    566         ESTM_PRINTF(("      -     "));
    567     }
    568     ESTM_PRINTF(("     %1d     ",rd_tx_pmd_dp_invert()));
    569 
    570     ESTM(enabled = rd_prbs_chk_en());
    571     if(enabled) {
    572         enum srds_prbs_polynomial_enum prbs_poly_mode = PRBS_7;
    573         enum srds_prbs_checker_mode_enum prbs_checker_mode;
    574         uint8_t prbs_inv = 0;
    575         char *prbs_string;
    576         EFUN(blackhawk_tsc_get_rx_prbs_config(sa__, &prbs_poly_mode, &prbs_checker_mode, &prbs_inv));
    577         prbs_string = (char *)blackhawk_tsc_e2s_prbs_mode_enum[prbs_poly_mode];
    578         ESTM_PRINTF((" %s",prbs_string));
    579         ESTM_PRINTF(("      %1d     ",prbs_inv));
    580     } else {
    581         EFUN_PRINTF(("   OFF  "));
    582         ESTM_PRINTF(("      -     "));
    583     }
    584 
    585     ESTM_PRINTF(("     %1d     ",rd_rx_pmd_dp_invert()));
    586     ESTM_PRINTF(("  %d ",rd_prbs_chk_lock()));
    587     EFUN(blackhawk_tsc_prbs_err_count_state(sa__,&err_cnt,&lock_lost));
    588     EFUN_PRINTF(("  %d  %010d ",lock_lost,err_cnt));
    589     EFUN(blackhawk_tsc_INTERNAL_display_BER(sa__,100));
    590     EFUN_PRINTF(("\n"));
    591 
    592     return (ERR_CODE_NONE);
    593 }
    594 
    595 
    596 /***********************************/
    597 /*  PRBS Error Analyzer Functions  */
    598 /***********************************/
    599 
    600 /* Configure PRBS Error Analyzer */
    601 err_code_t blackhawk_tsc_prbs_error_analyzer_config(srds_access_t *sa__, uint16_t prbs_err_fec_size, uint8_t prbs_errcnt_thresh, uint8_t hist_errcnt_thresh) {
    602     uint8_t  fec_size;
    603     uint16_t fec_size_bits;
    604 
    605     if ((prbs_err_fec_size < BLACKHAWK_TSC_PRBS_ERR_ANALYZER_FEC_SIZE_MIN) || (prbs_err_fec_size > BLACKHAWK_TSC_PRBS_ERR_ANALYZER_FEC_SIZE_MAX)) { 
    606         return (blackhawk_tsc_error(sa__, ERR_CODE_INVALID_PRBS_ERR_ANALYZER_FEC_SIZE));
    607     }
    608     if ((prbs_errcnt_thresh < BLACKHAWK_TSC_PRBS_ERR_ANALYZER_ERR_THRESH_MIN) || (prbs_errcnt_thresh > BLACKHAWK_TSC_PRBS_ERR_ANALYZER_ERR_THRESH_MAX)) {
    609         return (blackhawk_tsc_error(sa__, ERR_CODE_INVALID_PRBS_ERR_ANALYZER_ERR_THRESH));
    610     }
    611     if ((hist_errcnt_thresh < BLACKHAWK_TSC_PRBS_ERR_ANALYZER_HIST_ERR_THRESH_MIN) || (hist_errcnt_thresh > BLACKHAWK_TSC_PRBS_ERR_ANALYZER_HIST_ERR_THRESH_MAX)) {
    612         return (blackhawk_tsc_error(sa__, ERR_CODE_INVALID_PRBS_ERR_ANALYZER_HIST_ERR_THRESH));
    613     }
    614 
    615     fec_size = ((prbs_err_fec_size + BLACKHAWK_TSC_PRBS_FEC_FRAME_SIZE_ROUND_UP) / BLACKHAWK_TSC_PRBS_FEC_FRAME_SIZE_MULTIPLIER);
    616 
    617     fec_size_bits = (fec_size * BLACKHAWK_TSC_PRBS_FEC_FRAME_SIZE_MULTIPLIER);
    618     if (prbs_err_fec_size != fec_size_bits) {
    619         EFUN_PRINTF(("\n << WARNING: FEC Frame size of %d bits NOT programmable. Instead setting frame size to %d bits for Lane %d >>\n", prbs_err_fec_size, fec_size_bits, blackhawk_tsc_get_lane(sa__)));
    620     }
    621 
    622     EFUN(wr_tlb_err_fec_size(fec_size));
    623     EFUN(wr_tlb_err_error_count_thresh(prbs_errcnt_thresh));
    624     EFUN(wr_tlb_err_histogram_error_thresh(hist_errcnt_thresh));
    625     EFUN(wr_tlb_err_clear_error_analyzer_status(1));                                         /* Clear all the error analyzer status registers */
    626     return (ERR_CODE_NONE);
    627 }
    628 
    629 /* Get PRBS Error Analyzer Config */
    630 err_code_t blackhawk_tsc_get_prbs_error_analyzer_config(srds_access_t *sa__, uint16_t *prbs_err_fec_size, uint8_t *prbs_errcnt_thresh, uint8_t *hist_errcnt_thresh) {
    631 
    632     if(!prbs_err_fec_size || !prbs_errcnt_thresh || !hist_errcnt_thresh) {
    633         return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    634     }
    635 
    636     ESTM(*prbs_err_fec_size  = rd_tlb_err_fec_size());
    637     *prbs_err_fec_size       = *prbs_err_fec_size * BLACKHAWK_TSC_PRBS_FEC_FRAME_SIZE_MULTIPLIER;
    638     ESTM(*prbs_errcnt_thresh = rd_tlb_err_error_count_thresh());
    639     ESTM(*hist_errcnt_thresh = rd_tlb_err_histogram_error_thresh());
    640     return (ERR_CODE_NONE);
    641 }
    642 
    643 /* Display PRBS Error Analyzer Config */
    644 err_code_t blackhawk_tsc_display_prbs_error_analyzer_config(srds_access_t *sa__, uint8_t prbs_errcnt_thresh, uint8_t hist_errcnt_thresh, uint32_t timeout_s) {
    645 
    646     uint8_t  fec_size;
    647     uint16_t fec_size_bits;
    648 
    649     ESTM(fec_size = (uint8_t)rd_tlb_err_fec_size());
    650     fec_size_bits = (fec_size * BLACKHAWK_TSC_PRBS_FEC_FRAME_SIZE_MULTIPLIER);
    651 
    652     EFUN_PRINTF(("\n ****************************************************************************** \n"));
    653     EFUN_PRINTF(("  PRBS Error Analyzer Config:\n"));
    654     EFUN_PRINTF((" ------------------------------------------------------------- \n"));
    655     EFUN_PRINTF(("    FEC Frame Size               = %4d bits\n",fec_size_bits));
    656     EFUN_PRINTF(("    PRBS Max Err Threshold (Max) = %4d errors per frame\n",prbs_errcnt_thresh));
    657     EFUN_PRINTF(("    PRBS Histogram Start (E)     = %4d errors per frame\n",hist_errcnt_thresh));
    658     EFUN_PRINTF(("    Time Duration of Analysis    = %4d seconds\n",timeout_s));
    659     EFUN_PRINTF((" -------------------------------------------------------------\n"));
    660 
    661     return (ERR_CODE_NONE);
    662 }
    663 
    664 /* Get PRBS Error Analyzer Error Count */
    665 err_code_t blackhawk_tsc_prbs_error_analyzer_err_count(srds_access_t *sa__, blackhawk_tsc_prbs_err_analyzer_errcnt_st *err_analyzer) {
    666     uint16_t err_cnt;
    667     uint8_t  prbs_lock;
    668     int8_t   i;
    669 
    670     if(!err_analyzer) {
    671         return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    672     }
    673 
    674     ESTM(err_analyzer->hist_errcnt_thresh = rd_tlb_err_histogram_error_thresh());
    675     ESTM(err_analyzer->prbs_errcnt_thresh = rd_tlb_err_error_count_thresh());
    676 
    677     ESTM(prbs_lock = rd_prbs_chk_lock());
    678     if(!prbs_lock) {
    679         USR_PRINTF(("\nERROR : PRBS Checker is not locked for core %d Lane %d\n",blackhawk_tsc_get_core(sa__),blackhawk_tsc_get_lane(sa__)));
    680         for (i=0; i<9; i++) {
    681             err_analyzer->prbs_errcnt[i] = 0xFFFFFFFF;
    682         }
    683     }
    684     else {
    685         uint32_t frame_errors[9];
    686         uint32_t temp32;
    687 
    688         /* Reading raw data from FEC err_count registers */
    689         ESTM(frame_errors[8] = rd_tlb_err_count_error_lo());
    690         ESTM(err_cnt = rd_tlb_err_count_error_hi());
    691         frame_errors[8] = (frame_errors[8] | (((uint32_t) err_cnt)<<16));
    692 
    693         ESTM(frame_errors[7] = rd_tlb_err_count_histogram_error_offset_7());
    694         ESTM(frame_errors[6] = rd_tlb_err_count_histogram_error_offset_6());
    695         ESTM(frame_errors[5] = rd_tlb_err_count_histogram_error_offset_5());
    696         ESTM(frame_errors[4] = rd_tlb_err_count_histogram_error_offset_4());
    697         ESTM(frame_errors[3] = rd_tlb_err_count_histogram_error_offset_3());
    698         ESTM(frame_errors[2] = rd_tlb_err_count_histogram_error_offset_2());
    699         ESTM(frame_errors[1] = rd_tlb_err_count_histogram_error_offset_1());
    700         ESTM(frame_errors[0] = rd_tlb_err_count_histogram_error_offset_0());
    701 
    702         if (PRBS_VERBOSE > 2) {
    703             EFUN_PRINTF(("\n\n\t=====> DEBUG INFO (start) [Core = %d, Lane = %d]\n", blackhawk_tsc_get_core(sa__), blackhawk_tsc_get_lane(sa__)));
    704             EFUN_PRINTF(("\n\t << Number of Frame Errors as read from the register >>\n"));
    705             for (i=0; i<9; i++) {
    706                 if (i < 8) {
    707                     EFUN_PRINTF(("\t FEC frames with   %2d Errors = %u\n",(i+err_analyzer->hist_errcnt_thresh),frame_errors[i]));
    708                 }
    709                 else {
    710                     EFUN_PRINTF(("\t FEC frames with > %2d Errors = %u\n",err_analyzer->prbs_errcnt_thresh-1,frame_errors[i]));
    711                 }
    712             }
    713         }
    714 
    715         /* Calculating cumulative error count for respective values of "t" */
    716         for (i=8; i >= 0; i--) {
    717             if ((frame_errors[i] != 0xFFFF) && (frame_errors[i] != 0xFFFFF)) {
    718                 if (i!=8) {
    719                     if (frame_errors[i+1] == 0xFFFFFFFF) {
    720                         frame_errors[i] = 0xFFFFFFFF;
    721                     }
    722                     else {
    723                         frame_errors[i] = (frame_errors[i] + frame_errors[i+1]);
    724                     }
    725                 }
    726             }
    727             else {
    728 
    729                 if (PRBS_VERBOSE > 2) {
    730                     EFUN_PRINTF(("\t frame_errors[%d] == MAX\n", i));
    731                 }
    732 
    733                 frame_errors[i] = 0xFFFFFFFF;
    734             }
    735         }
    736 
    737         if (PRBS_VERBOSE > 2) {
    738             EFUN_PRINTF(("\n\t=====> DEBUG INFO (end)\n\n"));
    739         }
    740 
    741         /* Accumulating error counts and assigning to struct */
    742         for (i=0; i<9; i++) {
    743             temp32 = 0xFFFFFFFF - frame_errors[i];
    744             if ((frame_errors[i] == 0xFFFFFFFF) || (temp32 <= err_analyzer->prbs_errcnt[i]))
    745                 err_analyzer->prbs_errcnt[i] = 0xFFFFFFFF;
    746             else
    747                 err_analyzer->prbs_errcnt[i] = (frame_errors[i] + err_analyzer->prbs_errcnt[i]);
    748         }
    749     }
    750     return (ERR_CODE_NONE);
    751 }
    752 
    753 /* Get PRBS Error Analyzer Accumulate Error Count and Clear error counters */
    754 err_code_t blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(srds_access_t *sa__, blackhawk_tsc_prbs_err_analyzer_errcnt_st *err_analyzer) {
    755 
    756     EFUN(blackhawk_tsc_prbs_error_analyzer_err_count(sa__, err_analyzer));
    757     return (ERR_CODE_NONE);
    758 }
    759 
    760 static err_code_t _blackhawk_tsc_display_fec_frame_error(uint8_t errs_per_frame, uint32_t num_frame_errs) {
    761     if (num_frame_errs == 0xFFFFFFFF) {
    762         EFUN_PRINTF(("    FEC Frames with > %2d Errors (t=%2d) =        MAX \n",errs_per_frame,errs_per_frame));
    763     }
    764     else {
    765         EFUN_PRINTF(("    FEC Frames with > %2d Errors (t=%2d) = %10u \n",errs_per_frame,errs_per_frame,num_frame_errs));
    766     }
    767     return (ERR_CODE_NONE);
    768 }
    769 
    770 /* Optimize histogram error count threshold for PRBS Error Analyzer */
    771 err_code_t blackhawk_tsc_optimize_hist_errcnt_thresh(srds_access_t *sa__, blackhawk_tsc_prbs_err_analyzer_errcnt_st *err_analyzer, uint32_t timeout_check, uint32_t timeout_s) {
    772     int8_t  i = 0;
    773     uint8_t errcnt_sat = 0;
    774 #ifdef PHYMOD_SUPPORT
    775     uint64_t tmp_err, tmp_sat;
    776 #endif /* PHYMOD_SUPPORT */
    777 
    778     if((timeout_check == 0) || timeout_s == 0) {
    779         USR_PRINTF(("\nERROR : timeout value cannot be 0 for RX lane %d\n",blackhawk_tsc_get_lane(sa__)));
    780     }
    781     if(timeout_check > timeout_s) {
    782         USR_PRINTF(("\nERROR : timeout_check value has to be <= timeout_s value for RX lane %d\n",blackhawk_tsc_get_lane(sa__)));
    783     }
    784 
    785     /* Read the current histogram settings*/
    786     ESTM(err_analyzer->hist_errcnt_thresh = rd_tlb_err_histogram_error_thresh());
    787 
    788     /* Extrapolate and check for saturation */
    789 #ifdef PHYMOD_SUPPORT
    790     for(i = BLACKHAWK_TSC_PRBS_ERR_ANALYZER_NUM_COUNTERS-1; i>=0 ; i--) {
    791         /*
    792          * 64-bit operations use COMPILER_64_XXX macros
    793          */
    794         /* tmp_err = (uint64_t)timeout_s * err_analyzer->prbs_errcnt[i] */
    795         COMPILER_64_SET(tmp_err, 0, (uint32_t)1);
    796         COMPILER_64_UMUL_32(tmp_err, timeout_s);
    797         COMPILER_64_UMUL_32(tmp_err, err_analyzer->prbs_errcnt[i]);
    798 
    799         /* tmp_sat = (uint64_t)timeout_check * 0xFFFF */
    800         COMPILER_64_SET(tmp_sat, 0, (uint32_t)1);
    801         COMPILER_64_UMUL_32(tmp_sat, timeout_check);
    802         COMPILER_64_UMUL_32(tmp_sat, 0xFFFF);
    803 
    804         if (COMPILER_64_GE(tmp_err, tmp_sat)) {
    805             errcnt_sat = 1;
    806             break;
    807         }
    808     }
    809 #else
    810     for(i = BLACKHAWK_TSC_PRBS_ERR_ANALYZER_NUM_COUNTERS-1; i>=0 ; i--) {
    811         if((uint64_t)timeout_s * err_analyzer->prbs_errcnt[i] > (uint64_t)timeout_check * (0xFFFF)) {
    812             errcnt_sat = 1;
    813             break;
    814         }
    815     }
    816 #endif /* PHYMOD_SUPPORT */
    817 
    818     if((errcnt_sat == 1) && (i != 0)) {
    819         if((i+err_analyzer->hist_errcnt_thresh) >= BLACKHAWK_TSC_PRBS_ERR_ANALYZER_HIST_ERR_THRESH_MAX) {
    820             err_analyzer->hist_errcnt_thresh = BLACKHAWK_TSC_PRBS_ERR_ANALYZER_HIST_ERR_THRESH_MAX-1;
    821             err_analyzer->prbs_errcnt_thresh = BLACKHAWK_TSC_PRBS_ERR_ANALYZER_ERR_THRESH_MAX;
    822             EFUN_PRINTF(("\tLane %d: Setting the histogram error count threshold to maximum value = %d and PRBS error count threshold = %d\n \n ", blackhawk_tsc_get_lane(sa__), err_analyzer->hist_errcnt_thresh, BLACKHAWK_TSC_PRBS_ERR_ANALYZER_ERR_THRESH_MAX));
    823 
    824         } else {
    825             err_analyzer->hist_errcnt_thresh += i;
    826             err_analyzer->prbs_errcnt_thresh = err_analyzer->hist_errcnt_thresh + 8;
    827             EFUN_PRINTF(("\tLane %d: Optimum histogram error count threshold found\n", blackhawk_tsc_get_lane(sa__)));
    828             USR_PRINTF(("           Changing histogram error count threshold to %d and PRBS error count threshold to %d\n \n ", err_analyzer->hist_errcnt_thresh, err_analyzer->prbs_errcnt_thresh));
    829         }
    830         /* Reconfigure */
    831         EFUN(wr_tlb_err_histogram_error_thresh(err_analyzer->hist_errcnt_thresh));
    832         EFUN(wr_tlb_err_error_count_thresh(err_analyzer->prbs_errcnt_thresh));
    833     } else if ((err_analyzer->prbs_errcnt[0] == 0) && (err_analyzer->hist_errcnt_thresh != BLACKHAWK_TSC_PRBS_ERR_ANALYZER_ERR_THRESH_MIN)) {
    834         EFUN_PRINTF(("\tLane %d: WARNING: Error counters are all 0 after %ds. Try reducing hist_errcnt_thresh or increasing timeout_check and rerun the projection\n \n ", blackhawk_tsc_get_lane(sa__), timeout_check));
    835     } else if ((err_analyzer->prbs_errcnt[0] == 0) && (err_analyzer->hist_errcnt_thresh == BLACKHAWK_TSC_PRBS_ERR_ANALYZER_ERR_THRESH_MIN)) {
    836         EFUN_PRINTF(("\tLane %d: WARNING: Error counters are all 0 after %ds. Try increasing timeout_check and/or timeout and rerun the projection\n \n ", blackhawk_tsc_get_lane(sa__), timeout_check));
    837     } else {
    838         EFUN_PRINTF(("\tLane %d: Current hist_errcnt_thresh is the optimized value. Value = %d is unchanged. \n \n ", blackhawk_tsc_get_lane(sa__), err_analyzer->hist_errcnt_thresh));
    839     }
    840 
    841     /* Clear all the error analyzer status registers */
    842     EFUN(wr_tlb_err_clear_error_analyzer_status(1));
    843 
    844     return (ERR_CODE_NONE);
    845 }
    846 
    847 /* PRBS Error Analyzer Display */
    848 err_code_t blackhawk_tsc_display_prbs_error_analyzer_err_count(srds_access_t *sa__, blackhawk_tsc_prbs_err_analyzer_errcnt_st err_analyzer) {
    849     uint8_t t, i;
    850 
    851     t = err_analyzer.hist_errcnt_thresh - 1;                                      /* number of FEC correctable errors */
    852 
    853     /* Display PRBS Error Analyzer Err_Counts */
    854     EFUN_PRINTF(("\n -------------------------------------------------------------\n"));
    855     EFUN_PRINTF(("  PRBS Error Analyzer Error_Counts:\n"));
    856     EFUN_PRINTF((" -------------------------------------------------------------\n"));
    857     for (i=0; i<8; i++) {
    858         EFUN(_blackhawk_tsc_display_fec_frame_error(t+i, err_analyzer.prbs_errcnt[i]));
    859     }
    860     EFUN(_blackhawk_tsc_display_fec_frame_error(err_analyzer.prbs_errcnt_thresh-1, err_analyzer.prbs_errcnt[8]));
    861     EFUN_PRINTF((" -------------------------------------------------------------\n"));
    862 
    863     return (ERR_CODE_NONE);
    864 }
    865 
    866 
    867 /* Display PRBS Error Analyzer Projection */
    868 err_code_t blackhawk_tsc_display_prbs_error_analyzer_proj(srds_access_t *sa__, uint16_t prbs_err_fec_size, uint8_t hist_errcnt_thresh, uint32_t timeout_s) {
    869     uint8_t  hrs, mins, secs;
    870     uint8_t  prbs_lock;
    871     uint32_t time_remaining_s;
    872     int8_t  i = 0;
    873     blackhawk_tsc_prbs_err_analyzer_errcnt_st err_analyzer;
    874 
    875     if (timeout_s == 0) {
    876         EFUN_PRINTF(("\nERROR: timeout_s value cannot be 0 for Lane %d >>\n", blackhawk_tsc_get_lane(sa__)));
    877     }
    878 
    879     ESTM(prbs_lock = rd_prbs_chk_lock());
    880     if(!prbs_lock) {
    881         USR_PRINTF(("\nERROR : PRBS Checker is not locked for RX lane %d\n",blackhawk_tsc_get_lane(sa__)));
    882     }
    883     else {
    884     USR_MEMSET(&err_analyzer, 0, sizeof(blackhawk_tsc_prbs_err_analyzer_errcnt_st));
    885         err_analyzer.prbs_errcnt_thresh = hist_errcnt_thresh + 8;     /* Since 20bit err_cnt register counts Frames with errors >= prbs_errcnt_thresh errors */
    886         err_analyzer.hist_errcnt_thresh = hist_errcnt_thresh;
    887         EFUN(blackhawk_tsc_prbs_error_analyzer_config(sa__, prbs_err_fec_size, err_analyzer.prbs_errcnt_thresh, err_analyzer.hist_errcnt_thresh));  /* Configure PRBS Error Analyzer */
    888         EFUN(wr_tlb_err_clear_status_on_read(1));        
    889         /* Clear the error counters for a fresh start */
    890         for (i = 0; i <= BLACKHAWK_TSC_PRBS_ERR_ANALYZER_NUM_COUNTERS; i++) {
    891            err_analyzer.prbs_errcnt[i] = 0;
    892         }
    893 
    894         EFUN(blackhawk_tsc_INTERNAL_seconds_to_displayformat(timeout_s, &hrs, &mins, &secs));
    895         EFUN_PRINTF((" \n Waiting for PRBS Error Analyzer measurement: time approx %d seconds (%d hr:%d mins: %ds) ",timeout_s,hrs,mins,secs));
    896 
    897         /* Wait for required duration and accumulate errors */
    898         time_remaining_s = timeout_s;
    899         while (time_remaining_s > 0) {
    900             if (time_remaining_s > 5) {
    901                 EFUN(USR_DELAY_MS(5000));
    902                 EFUN(blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(sa__, &err_analyzer));
    903                 EFUN_PRINTF(("."));
    904                 time_remaining_s = time_remaining_s - 5;
    905             }
    906             else {
    907                 EFUN(USR_DELAY_MS(((uint32_t)time_remaining_s) * 1000));
    908                 EFUN(blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(sa__, &err_analyzer));
    909                 EFUN_PRINTF(("\n"));
    910                 time_remaining_s = 0;
    911             }
    912         }
    913 
    914         /* Display PRBS Error Analyzer Config */
    915         EFUN(blackhawk_tsc_display_prbs_error_analyzer_config(sa__, err_analyzer.prbs_errcnt_thresh, err_analyzer.hist_errcnt_thresh, timeout_s));
    916 
    917         /* Display PRBS Error Analyzer Err_Counts */
    918         EFUN(blackhawk_tsc_display_prbs_error_analyzer_err_count(sa__, err_analyzer));
    919 
    920         /* Compute and display PRBS Error Analyzer Projection */
    921         EFUN(blackhawk_tsc_prbs_error_analyzer_compute_proj(sa__, err_analyzer, timeout_s));
    922     }
    923     return (ERR_CODE_NONE);
    924 }
    925 
    926 /* Display PRBS Error Analyzer Projection with automatic threshold adjusting */
    927 err_code_t blackhawk_tsc_display_prbs_error_analyzer_proj_auto_threshold(srds_access_t *sa__, uint16_t prbs_err_fec_size, uint32_t timeout_s) {
    928     uint8_t  hrs, mins, secs;
    929     uint8_t  prbs_lock;
    930     uint32_t time_remaining_s, timeout_frac;
    931     int8_t  i = 0;
    932     blackhawk_tsc_prbs_err_analyzer_errcnt_st err_analyzer;
    933 
    934     if (timeout_s == 0) {
    935         EFUN_PRINTF(("\nERROR: timeout_s value cannot be 0 for Lane %d >>\n", blackhawk_tsc_get_lane(sa__)));
    936     }
    937 
    938     ESTM(prbs_lock = rd_prbs_chk_lock());
    939     if(!prbs_lock) {
    940         USR_PRINTF(("\nERROR : PRBS Checker is not locked for RX lane %d\n",blackhawk_tsc_get_lane(sa__)));
    941     }
    942     else {
    943         USR_MEMSET(&err_analyzer, 0, sizeof(blackhawk_tsc_prbs_err_analyzer_errcnt_st));
    944         err_analyzer.hist_errcnt_thresh = BLACKHAWK_TSC_PRBS_ERR_ANALYZER_HIST_ERR_THRESH_MIN;
    945         err_analyzer.prbs_errcnt_thresh = err_analyzer.hist_errcnt_thresh + 8;     /* Since 20bit err_cnt register counts Frames with errors >= prbs_errcnt_thresh errors */
    946 
    947         EFUN(blackhawk_tsc_prbs_error_analyzer_config(sa__, prbs_err_fec_size, err_analyzer.prbs_errcnt_thresh, err_analyzer.hist_errcnt_thresh));  /* Configure PRBS Error Analyzer */
    948 
    949         EFUN(wr_tlb_err_clear_status_on_read(1));        
    950 
    951         timeout_frac = (5*timeout_s+99)/100; /* 99 is used to generate CEIL function of 5% of timeout_s */
    952         EFUN(blackhawk_tsc_INTERNAL_seconds_to_displayformat(timeout_frac, &hrs, &mins, &secs));
    953         EFUN_PRINTF(("\n \n Running a quick PRBS Error Analyzer measurement : time approx %d seconds (%d hr:%d mins: %ds) to check if any error counters would saturate\n \n ",timeout_frac,hrs,mins,secs));
    954 
    955         /* Run a quick test (5% of timeout_s) and optimize the hist_errcnt_thresh */
    956         EFUN(USR_DELAY_MS(1000*timeout_frac));
    957         EFUN(blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(sa__, &err_analyzer));
    958         EFUN(blackhawk_tsc_optimize_hist_errcnt_thresh(sa__, &err_analyzer, timeout_frac, timeout_s));
    959 
    960         /* Clear the error counters for a fresh start */
    961         for (i = 0; i <= BLACKHAWK_TSC_PRBS_ERR_ANALYZER_NUM_COUNTERS; i++) {
    962            err_analyzer.prbs_errcnt[i] = 0;
    963         }
    964 
    965         EFUN(blackhawk_tsc_INTERNAL_seconds_to_displayformat(timeout_s, &hrs, &mins, &secs));
    966         EFUN_PRINTF((" \n Waiting for PRBS Error Analyzer measurement: time approx %d seconds (%d hr:%d mins: %ds) ",timeout_s,hrs,mins,secs));
    967 
    968         /* Wait for required duration and accumulate errors */
    969         time_remaining_s = timeout_s;
    970         while (time_remaining_s > 0) {
    971             if (time_remaining_s > 5) {
    972                 EFUN(USR_DELAY_MS(5000));
    973                 EFUN(blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(sa__, &err_analyzer));
    974                 EFUN_PRINTF(("."));
    975                 time_remaining_s = time_remaining_s - 5;
    976             }
    977             else {
    978                 EFUN(USR_DELAY_MS(((uint32_t)time_remaining_s) * 1000));
    979                 EFUN(blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(sa__, &err_analyzer));
    980                 EFUN_PRINTF(("\n"));
    981                 time_remaining_s = 0;
    982             }
    983         }
    984 
    985         /* Display PRBS Error Analyzer Config */
    986         EFUN(blackhawk_tsc_display_prbs_error_analyzer_config(sa__, err_analyzer.prbs_errcnt_thresh, err_analyzer.hist_errcnt_thresh, timeout_s));
    987 
    988         /* Display PRBS Error Analyzer Err_Counts */
    989         EFUN(blackhawk_tsc_display_prbs_error_analyzer_err_count(sa__, err_analyzer));
    990 
    991         /* Compute and display PRBS Error Analyzer Projection */
    992         EFUN(blackhawk_tsc_prbs_error_analyzer_compute_proj(sa__, err_analyzer, timeout_s));
    993     }
    994     return (ERR_CODE_NONE);
    995 }
    996 
    997 
    998 /*----------------------------------------------------------------------------------------------------------------*/
    999 /* Following calculations are used for projecting the Bit Error Rate (BER) from the PRBS Error Analyzer result    */
   1000 /*  - test_time_in_bits     = test_time_ms * num_bits_per_ms                                                      */
   1001 /*  - num_frames_in_test    = test_time_in_bits / (num_bits_per_frame * frame_overlap_ratio)                      */
   1002 /*  - frame_err_rate  (FER) = num_frame_errors / num_frames_in_test                                               */
   1003 /*  - bit_err_rate    (BER) = FER / num_bits_per_frame                                                            */
   1004 /*                  => BER  = (num_frame_errors * frame_overlap_ratio) / (test_time_ms * num_bits_per_ms)         */
   1005 /*                            where, frame_overlap_ratio = 1 / frame_overlap_factor                               */
   1006 /*                                                                                                                */
   1007 /* Following guidelines are used while computing projected values -                                               */
   1008 /*   i) Only "frame_errors" that are in between "10 and 65535" are considered as valid data points for projection */
   1009 /*  ii) Need atleast 2 valid data points to generated projected data                                              */
   1010 /*----------------------------------------------------------------------------------------------------------------*/
   1011 err_code_t blackhawk_tsc_prbs_error_analyzer_report_proj(srds_access_t *sa__, blackhawk_tsc_prbs_err_analyzer_errcnt_st err_analyzer, uint32_t timeout_s, blackhawk_tsc_prbs_err_analyzer_report_st *err_analyzer_report) {
   1012 #ifdef SERDES_API_FLOATING_POINT
   1013     uint8_t    t, delta_n;
   1014     int8_t     i;
   1015     uint8_t    start_idx, stop_idx;
   1016     uint32_t   num_bits_per_ms;
   1017     USR_DOUBLE meas_fec_ber[9];
   1018     USR_DOUBLE proj_ber[16];
   1019     USR_DOUBLE x, y;
   1020     USR_DOUBLE Exy = 0.0;
   1021     USR_DOUBLE Eyy = 0.0;
   1022     USR_DOUBLE Exx = 0.0;
   1023     USR_DOUBLE Ey  = 0.0;
   1024     USR_DOUBLE Ex  = 0.0;
   1025     USR_DOUBLE alpha = 0.0, alpha2 = 0.0, sq_r = 0.0;
   1026     USR_DOUBLE beta = 0.0;
   1027 
   1028     if (timeout_s == 0) {
   1029         EFUN_PRINTF(("\nERROR: timeout_s value cannot be 0 for Lane %d >>\n", blackhawk_tsc_get_lane(sa__)));
   1030         return(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1031     }
   1032 
   1033     USR_MEMSET(err_analyzer_report, 0, sizeof(blackhawk_tsc_prbs_err_analyzer_report_st));
   1034     t = err_analyzer.hist_errcnt_thresh - 1;                                                       /* Number of FEC correctable errors */
   1035     EFUN(blackhawk_tsc_INTERNAL_get_num_bits_per_ms(sa__, &num_bits_per_ms));
   1036 
   1037     if (num_bits_per_ms == 0) {
   1038         EFUN_PRINTF(("\nERROR: num_bits_per_ms value cannot be 0 for Lane %d >>\n", blackhawk_tsc_get_lane(sa__)));
   1039         return(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1040     }
   1041 
   1042     if (PRBS_VERBOSE > 2) {
   1043         EFUN_PRINTF(("\n\t=====> DEBUG INFO (start)\n"));
   1044         EFUN_PRINTF(("\n\t << Measured Equivalent BER for specific error correcting FEC >>\n"));
   1045     }
   1046 
   1047     /* Loop to calculate the measured BER based on above mentioned calculations */
   1048 
   1049     for(i=0; i < 9; i++) {
   1050         meas_fec_ber[i] = ((((USR_DOUBLE)(err_analyzer.prbs_errcnt[i]) / (USR_DOUBLE) BLACKHAWK_TSC_PRBS_ERR_ANALYZER_FRAME_OVERLAP_FACTOR) / (USR_DOUBLE)(timeout_s * 1000)) / (USR_DOUBLE) num_bits_per_ms);
   1051         if (PRBS_VERBOSE > 2) {
   1052             EFUN_PRINTF(("\t Measured Equivalent BER at 't=%2d' (((frameErr/overlap_factor)/time_ms)/rate) = (((%u/%d)/%d)/%d): %0.3e \n",(t+i), err_analyzer.prbs_errcnt[i],
   1053                                                                                 BLACKHAWK_TSC_PRBS_ERR_ANALYZER_FRAME_OVERLAP_FACTOR, timeout_s*1000, num_bits_per_ms, meas_fec_ber[i]));
   1054         }
   1055     }
   1056 
   1057     /* Calculating number of MEASURED points available for extrapolation */
   1058     /* start_idx - first non-max FEC frame error value; stop_idx - index where FEC frame errors < 10 errors */
   1059     start_idx = 0;
   1060     stop_idx  = 0;
   1061     if (err_analyzer.prbs_errcnt[8] != 0xFFFFFFFF) {
   1062         stop_idx  = 9;
   1063     }
   1064     for (i=8; i >= 0; i--) {
   1065         if (err_analyzer.prbs_errcnt[i] != 0xFFFFFFFF) {
   1066             start_idx = i;
   1067         }
   1068         if (err_analyzer.prbs_errcnt[i] < 10*BLACKHAWK_TSC_PRBS_ERR_ANALYZER_FRAME_OVERLAP_FACTOR) {  /* "10*BLACKHAWK_TSC_PRBS_ERR_ANALYZER_FRAME_OVERLAP_FACTOR"  means  "10 error events" */
   1069             stop_idx = i;
   1070         }
   1071     }
   1072     delta_n = stop_idx - start_idx;                                                  /* Number of MEASURED points available for extrapolation */
   1073 
   1074     /* Compute covariance and mean for extrapolation */
   1075     if (delta_n >= 2) {                                                              /* There are at least 2 points to trace a line for extrapolation */
   1076         for(i=start_idx; i < stop_idx; i++) {
   1077             x    = (USR_DOUBLE) (t + i);
   1078             y    = pow((-log10(meas_fec_ber[i])),BLACKHAWK_TSC_PRBS_ERR_ANALYZER_LINEARITY_ADJUST);
   1079             Exy += ((x * y)/(USR_DOUBLE)delta_n);
   1080             Eyy += ((y * y)/(USR_DOUBLE)delta_n);
   1081             Exx += ((x * x)/(USR_DOUBLE)delta_n);
   1082             Ey  += ((  y  )/(USR_DOUBLE)delta_n);
   1083             Ex  += ((  x  )/(USR_DOUBLE)delta_n);
   1084         }
   1085 
   1086         /* Compute fit slope and offset: ber = alpha*frame_err_thresh + beta */
   1087         alpha = (Exy - Ey*Ex) / (Exx - Ex*Ex);
   1088         beta  = Ey - Ex*alpha;
   1089         /* Compute alpha2: slope of regression: frame_err_thresh = alpha2*ber + beta2 */
   1090         alpha2 = (Exy - Ey*Ex) / (Eyy - Ey*Ey);
   1091         /* Compute correlation index sq_r */
   1092         sq_r = alpha*alpha2;
   1093     }
   1094 
   1095     if (PRBS_VERBOSE > 2) {
   1096         EFUN_PRINTF(("\n\t << Computing linear fit from Measured Equivalent BER points >>\n"));
   1097         EFUN_PRINTF(("\t Number of measured points used for extrapolation = %d\n",delta_n));
   1098         EFUN_PRINTF(("\t Exy=%lf, Eyy=%lf, Exx=%lf, Ey=%lf, Ex=%lf\n",Exy,Eyy,Exx,Ey,Ex));
   1099         EFUN_PRINTF(("\t alpha=%lf, beta=%lf\n",alpha,beta));
   1100         EFUN_PRINTF(("\t sq_r=%lf\n",sq_r));
   1101         EFUN_PRINTF(("\n\t=====> DEBUG INFO (end)\n\n"));
   1102     }
   1103 
   1104 
   1105     /* Calulate Projected BER => Equivalent projected post-FEC BER for t=15 */
   1106     if (delta_n >= 2) {
   1107         proj_ber[15] = ((alpha * 15) + beta);
   1108         proj_ber[15] = pow(proj_ber[15],1.0/BLACKHAWK_TSC_PRBS_ERR_ANALYZER_LINEARITY_ADJUST);
   1109         proj_ber[15] = pow(10,-proj_ber[15]);
   1110     }
   1111     else {
   1112         proj_ber[15] = 0.0;
   1113     }
   1114 
   1115 
   1116 
   1117     /* Populate output structure */
   1118     err_analyzer_report->proj_ber  = proj_ber[15];
   1119     err_analyzer_report->ber_proj_invalid  = 0;       /* To be populated: 0 -> valid, +1 -> BER greater than; -1 -> BER less than */
   1120     err_analyzer_report->delta_n   = delta_n;
   1121     return (ERR_CODE_NONE);
   1122 #else
   1123     UNUSED(err_analyzer);
   1124     UNUSED(timeout_s);
   1125     UNUSED(*err_analyzer_report);
   1126     EFUN_PRINTF(("This function needs SERDES_API_FLOATING_POINT define to operate \n"));
   1127     return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
   1128 #endif /* SERDES_API_FLOATING_POINT */
   1129 }
   1130 
   1131 err_code_t blackhawk_tsc_prbs_error_analyzer_compute_proj(srds_access_t *sa__, blackhawk_tsc_prbs_err_analyzer_errcnt_st err_analyzer, uint32_t timeout_s) {
   1132 
   1133 #ifdef SERDES_API_FLOATING_POINT
   1134     blackhawk_tsc_prbs_err_analyzer_report_st err_analyzer_rep;
   1135 
   1136     if (timeout_s == 0) {
   1137         EFUN_PRINTF(("\nERROR: timeout_s value cannot be 0 for Lane %d >>\n", blackhawk_tsc_get_lane(sa__)));
   1138     }
   1139 
   1140     EFUN(blackhawk_tsc_prbs_error_analyzer_report_proj(sa__, err_analyzer, timeout_s,  &err_analyzer_rep));
   1141 
   1142 
   1143     /* Displaying Projected BER => Equivalent projected post-FEC BER for t=15 */
   1144     if (err_analyzer_rep.delta_n >= 2) {
   1145         EFUN_PRINTF(("\n  PRBS Error Analyzer Projected BER (Equivalent projected post-FEC BER for t=15) for Lane %d = %0.3e\n\n",blackhawk_tsc_get_lane(sa__), err_analyzer_rep.proj_ber));
   1146     }
   1147     else {
   1148         EFUN_PRINTF(("\n << WARNING: Not enough valid measured points available for BER Projection for Lane %d ! >>\n\n",blackhawk_tsc_get_lane(sa__)));
   1149     }
   1150 
   1151 #else
   1152     UNUSED(err_analyzer);
   1153     UNUSED(timeout_s);
   1154 #endif /* SERDES_API_FLOATING_POINT */
   1155 
   1156 
   1157     return (ERR_CODE_NONE);
   1158 }
   1159 
   1160 err_code_t blackhawk_tsc_get_prbsfb_status(srds_access_t *sa__, uint8_t *done_once) {
   1161     /* D003_XX has this register read macro defined*/
   1162     uint16_t ucode_version_major;
   1163     /*Extracting the major version number*/
   1164     ESTM(ucode_version_major = rdcv_common_ucode_version() & 0xFFF);
   1165     if (ucode_version_major >= 0x3) {
   1166         ESTM((*done_once = rdv_opt_err_pam4_prbsfb_byte_byte() & 0x40));
   1167     } else {
   1168         *done_once = 1;
   1169         EFUN_PRINTF(("ERROR: Need microcode version D003_xx for prbsfb status read to work correctly, setting done_once to 1 \n"));
   1170     }
   1171     return(ERR_CODE_NONE);
   1172 }
   1173 
   1174 
   1175