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_diag.c (93512B)


      1 /***********************************************************************************
      2  ***********************************************************************************
      3  *  File Name     :  blackhawk_tsc_diag.c                                             *
      4  *  Created On    :  03 Nov 2015                                                   *
      5  *  Created By    :  Brent Roberts                                                 *
      6  *  Description   :  Diagnostic 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_diag.c
     23  * Implementation of API functions
     24  */
     25 
     26 #ifdef EXCLUDE_STD_HEADERS
     27 #include <stdio.h>
     28 #include <math.h>
     29 #endif
     30 
     31 #ifdef SERDES_API_FLOATING_POINT
     32 #include <math.h>
     33 #endif
     34 
     35 #include <phymod/phymod_system.h>
     36 #include "blackhawk_tsc_diag.h"
     37 #include "blackhawk_tsc_access.h"
     38 #include "blackhawk_tsc_config.h"
     39 #include "blackhawk_tsc_debug_functions.h"
     40 #include "blackhawk_tsc_functions.h"
     41 #include "blackhawk_tsc_internal.h"
     42 #include "blackhawk_tsc_internal_error.h"
     43 #include "blackhawk_tsc_prbs.h"
     44 #include "blackhawk_tsc_select_defns.h"
     45 
     46 
     47 /************************************/
     48 /*  Display Eye Scan                */
     49 /************************************/
     50 
     51 
     52 /* Timestamp check to see if heartbeat timer is programmed correctly for the COMCLK frequency it is running at */
     53 err_code_t blackhawk_tsc_test_uc_timestamp(srds_access_t *sa__) {
     54 
     55 #ifdef SERDES_API_FLOATING_POINT
     56     uint16_t time;
     57     USR_DOUBLE resolution;
     58     const uint16_t test_delay=400;
     59 
     60     const USR_DOUBLE max_resolution=11.0;
     61     const USR_DOUBLE min_resolution=9.0;
     62 
     63     EFUN(blackhawk_tsc_pmd_uc_cmd(sa__, CMD_UC_DBG,CMD_UC_DBG_TIMESTAMP,100));
     64     ESTM(time=rd_uc_dsc_data());
     65     USR_DELAY_MS(test_delay);
     66     EFUN(blackhawk_tsc_pmd_uc_cmd(sa__, CMD_UC_DBG,CMD_UC_DBG_TIMESTAMP,100));
     67     ESTM(time=rd_uc_dsc_data()-time);
     68     resolution=test_delay*1000.0/(double)time;
     69     if((resolution<min_resolution)||(resolution>max_resolution)){
     70         EFUN_PRINTF(("\nERROR : Lane %i:\tuC timestamp: %i\t\tResolution: %.1fms/count. Passing resolution limits:\tMax: %.1fms/count\tMin: %.1fms/count\n",blackhawk_tsc_get_lane(sa__),time,resolution,max_resolution,min_resolution));
     71         return(ERR_CODE_DIAG_TIMESTAMP_FAIL);
     72     }
     73     else {
     74         EFUN_PRINTF(("\nPassed timestamp check : Lane %i:\tuC timestamp: %i\t\tResolution: %.1fms/count. Passing resolution limits:\tMax: %.1fms/count\tMin: %.1fms/count\n",blackhawk_tsc_get_lane(sa__),time,resolution,max_resolution,min_resolution));
     75    }
     76 #else
     77     EFUN_PRINTF(("This function needs SERDES_API_FLOATING_POINT define to operate \n"));
     78 #endif
     79     return(ERR_CODE_NONE);
     80 }
     81 
     82 
     83 /* This is best method for terminal ASCII display */
     84 err_code_t blackhawk_tsc_display_eye_scan(srds_access_t *sa__) {
     85     uint32_t   stripe[64] = {0};
     86     uint16_t   status = 0;
     87     int8_t     y,y_max,y_step;
     88 
     89     y_max  = EYE_SCAN_NRZ_VERTICAL_IDX_MAX;
     90     y_step = EYE_SCAN_NRZ_VERTICAL_STEP;
     91     {
     92         enum blackhawk_tsc_rx_pam_mode_enum pam_mode = NRZ;
     93         EFUN(blackhawk_tsc_INTERNAL_get_rx_pam_mode(sa__, &pam_mode));
     94         if (pam_mode == PAM4_NS) {
     95             y_max  = EYE_SCAN_PAM_VERTICAL_IDX_MAX;
     96             y_step = EYE_SCAN_PAM_VERTICAL_STEP;
     97         }
     98         else if (pam_mode == PAM4_ES) {
     99             y_max  = EYE_SCAN_PAM_VERTICAL_IDX_MAX;
    100             y_step = EYE_SCAN_PAM_VERTICAL_STEP;
    101             {
    102                 uint32_t version=0;
    103                 ESTM(version = rdcv_common_ucode_version() & 0x0FFF);
    104                 ESTM(version = (version<<8) | rdcv_common_ucode_minor_version());
    105                 if(version<0x0200) {
    106                     EFUN_PRINTF(("\n!!!2-D EYE SCAN IS NOT SUPPORTED FOR PAM4 ES MODE WITH THE CURRENT VERSION OF UCODE!!!\n\n"));
    107                     return (ERR_CODE_NONE);
    108                 }
    109             }
    110         }
    111     }
    112 
    113     EFUN(blackhawk_tsc_display_eye_scan_header(1));
    114 
    115     /* start horizontal acquisition */
    116     {   err_code_t err_code = blackhawk_tsc_meas_eye_scan_start(sa__, EYE_SCAN_HORIZ);
    117         if (err_code) {
    118             EFUN((blackhawk_tsc_meas_eye_scan_done(sa__), err_code));
    119         }
    120     }
    121 
    122     for (y = y_max;y>=-y_max;y=y-y_step)
    123     {
    124         {   err_code_t err_code = blackhawk_tsc_read_eye_scan_stripe(sa__, &stripe[0], &status);
    125             if (err_code) {
    126                 EFUN((blackhawk_tsc_meas_eye_scan_done(sa__), err_code));
    127             }
    128         }
    129         EFUN(blackhawk_tsc_display_eye_scan_stripe(sa__, y,&stripe[0]));
    130         EFUN_PRINTF(("\n"));
    131     }
    132     /* stop acquisition */
    133     EFUN(blackhawk_tsc_meas_eye_scan_done(sa__));
    134     EFUN(blackhawk_tsc_display_eye_scan_footer(1));
    135 
    136     return(ERR_CODE_NONE);
    137 }
    138 
    139 err_code_t blackhawk_tsc_meas_eye_scan_start(srds_access_t *sa__, uint8_t direction) {
    140     uint8_t lock;
    141 
    142     ESTM(lock = rd_pmd_rx_lock());
    143     if(lock == 0) {
    144           EFUN_PRINTF(("Error: No PMD_RX_LOCK on lane requesting 2D eye scan\n"));
    145           return(ERR_CODE_DIAG_SCAN_NOT_COMPLETE);
    146     }
    147     if(direction == EYE_SCAN_VERTICAL) {
    148         EFUN(blackhawk_tsc_pmd_uc_diag_cmd(sa__, CMD_UC_DIAG_START_VSCAN_EYE,GRACEFUL_STOP_TIME));
    149     } else if(direction == EYE_SCAN_HORIZ) {
    150         EFUN(blackhawk_tsc_pmd_uc_diag_cmd(sa__, CMD_UC_DIAG_START_HSCAN_EYE,GRACEFUL_STOP_TIME));
    151     } else if(direction == EYE_SCAN_SLICE) {
    152         EFUN(blackhawk_tsc_pmd_uc_diag_cmd(sa__, CMD_UC_DIAG_START_EYE_SLICE,GRACEFUL_STOP_TIME));
    153     }
    154     return(ERR_CODE_NONE);
    155 }
    156 
    157 err_code_t blackhawk_tsc_INTERNAL_poll_diag_data(srds_access_t *sa__, srds_info_t *blackhawk_tsc_info_ptr, uint16_t *status, uint8_t *diag_rd_ptr, uint8_t byte_count, uint32_t timeout_ms) {
    158     uint32_t lane_diag_size;
    159     uint16_t loop;
    160 
    161     CHECK_AND_RETURN_IF_NULL(blackhawk_tsc_info_ptr, ERR_CODE_INVALID_INFO_TABLE_ADDR);
    162     lane_diag_size = blackhawk_tsc_info_ptr->diag_mem_ram_size;
    163     *diag_rd_ptr = 0;
    164 
    165     if(!status) {
    166         return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    167     }
    168 
    169     /** If the byte_count is too high, then there might be problems not updating
    170      *  the read pointer fast enough.
    171      */
    172     if (byte_count > (lane_diag_size / 2)) {
    173         ESTM_PRINTF(("\nERROR : blackhawk_tsc_INTERNAL_poll_diag_data() has excessive byte count of %d.\n", byte_count));
    174         return (blackhawk_tsc_error(sa__, ERR_CODE_DIAG_TIMEOUT));
    175     }
    176 
    177     ESTM(*diag_rd_ptr = rdv_usr_diag_rd_ptr());
    178 
    179     /* Wait until byte_count bytes are available to be read in the diagnostic memory. */
    180     loop = 0;
    181     while (1) {
    182         uint8_t diag_wr_ptr, full_count;
    183 
    184         ESTM(diag_wr_ptr = rdv_usr_diag_wr_ptr());
    185         if (diag_wr_ptr >= *diag_rd_ptr) {
    186             full_count = diag_wr_ptr - *diag_rd_ptr;
    187         } else {
    188             full_count = (uint16_t)diag_wr_ptr + lane_diag_size - *diag_rd_ptr;
    189         }
    190         if (full_count >= byte_count) {
    191             break;
    192         }
    193 
    194         ++loop;
    195         if (loop > 10) {
    196             EFUN(USR_DELAY_US(10*timeout_ms));
    197         }
    198         if (loop > 1000) {
    199             return(blackhawk_tsc_error(sa__, ERR_CODE_DIAG_TIMEOUT));
    200         }
    201     }
    202     ESTM(*status = rdv_usr_diag_status() & 0xFF);
    203     return(ERR_CODE_NONE);
    204 }
    205 
    206 typedef struct {
    207     uint32_t *buffer_ptr;
    208     } blackhawk_tsc_read_eye_scan_stripe_callback_arg_t;
    209 
    210 static err_code_t blackhawk_tsc_read_eye_scan_stripe_callback(void *arg, uint8_t byte_count, uint16_t data) {
    211     blackhawk_tsc_read_eye_scan_stripe_callback_arg_t * const cast_arg = (blackhawk_tsc_read_eye_scan_stripe_callback_arg_t *)arg;
    212     *(cast_arg->buffer_ptr++) = blackhawk_tsc_INTERNAL_float8_to_int32((float8_t)(data & 0xFF));
    213     if (byte_count > 1) {
    214         *(cast_arg->buffer_ptr++) = blackhawk_tsc_INTERNAL_float8_to_int32((float8_t)(data >> 8));
    215     }
    216     return (ERR_CODE_NONE);
    217 }
    218 
    219 err_code_t blackhawk_tsc_read_eye_scan_stripe(srds_access_t *sa__, uint32_t *buffer, uint16_t *status) {
    220     srds_info_t * blackhawk_tsc_info_ptr = blackhawk_tsc_INTERNAL_get_blackhawk_tsc_info_ptr_with_check(sa__);
    221     const uint8_t lane = blackhawk_tsc_get_lane(sa__);
    222     const uint8_t stripe_size = 64;
    223 
    224     blackhawk_tsc_read_eye_scan_stripe_callback_arg_t arg;
    225     uint32_t lane_diag_base;
    226     uint8_t diag_rd_ptr;
    227 
    228 #ifdef PHYMOD_SUPPORT
    229     if ( blackhawk_tsc_info_ptr == NULL ) {
    230         blackhawk_tsc_init_blackhawk_tsc_info(sa__);
    231     } else if (blackhawk_tsc_info_ptr->signature != SRDS_INFO_SIGNATURE) {
    232         blackhawk_tsc_init_blackhawk_tsc_info(sa__);
    233     }
    234 #endif /* PHYMOD_SUPPORT */
    235 
    236     if(!buffer || !status) {
    237         return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    238     }
    239 
    240     EFUN(blackhawk_tsc_INTERNAL_verify_blackhawk_tsc_info(blackhawk_tsc_info_ptr, sa__));
    241 
    242         lane_diag_base = blackhawk_tsc_info_ptr->diag_mem_ram_base + ((lane%blackhawk_tsc_info_ptr->lane_count) * blackhawk_tsc_info_ptr->diag_mem_ram_size) +
    243             blackhawk_tsc_info_ptr->grp_ram_size*blackhawk_tsc_INTERNAL_grp_idx_from_lane(blackhawk_tsc_get_physical_lane(sa__));
    244 
    245     EFUN(blackhawk_tsc_INTERNAL_poll_diag_data(sa__, blackhawk_tsc_info_ptr, status, &diag_rd_ptr, stripe_size, 400));
    246 
    247     arg.buffer_ptr = buffer;
    248     EFUN(blackhawk_tsc_INTERNAL_rdblk_uc_generic_ram(sa__,
    249                                               lane_diag_base,
    250                                               blackhawk_tsc_info_ptr->diag_mem_ram_size,
    251                                               diag_rd_ptr,
    252                                               stripe_size,
    253                                               &arg,
    254                                               blackhawk_tsc_read_eye_scan_stripe_callback));
    255 
    256     diag_rd_ptr = ((uint32_t)diag_rd_ptr + stripe_size) % blackhawk_tsc_info_ptr->diag_mem_ram_size;
    257     EFUN(wrv_usr_diag_rd_ptr(diag_rd_ptr));
    258     ESTM(*status = rdv_usr_diag_status() & 0xFF);
    259     return(ERR_CODE_NONE);
    260 }
    261 
    262 err_code_t blackhawk_tsc_display_eye_scan_stripe(srds_access_t *sa__, int8_t y,uint32_t *buffer) {
    263 
    264     
    265     uint32_t limits[7] = {1835008, 183501, 18350, 1835, 184, 18, 2};
    266 
    267     int8_t x,i;
    268     int16_t level;
    269 
    270     enum blackhawk_tsc_rx_pam_mode_enum pam_mode = NRZ;
    271     EFUN(blackhawk_tsc_INTERNAL_get_rx_pam_mode(sa__, &pam_mode));
    272     if (pam_mode != NRZ) {
    273         for (i=0;i<7;i++) {
    274             limits[i] = limits[i] * 2;
    275         }
    276     }
    277 
    278     level = blackhawk_tsc_INTERNAL_ladder_setting_to_mV(sa__, y,0);
    279 
    280     if(!buffer) {
    281         return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    282     }
    283 
    284     EFUN_PRINTF(("%6dmV : ", level));
    285 
    286     for (x=-31;x<32;x++) {
    287         for (i=0;i<7;i++) {
    288             if (buffer[x+31]>=limits[i]) {
    289                 EFUN_PRINTF(("%c", '0'+i+1));
    290                 break;
    291             }
    292         }
    293         if (i==7) {
    294             if      ((x%5)==0 && (y%5)==0) {EFUN_PRINTF(("+"));}
    295             else if ((x%5)!=0 && (y%5)==0) {EFUN_PRINTF(("-"));}
    296             else if ((x%5)==0 && (y%5)!=0) {EFUN_PRINTF((":"));}
    297             else                           {EFUN_PRINTF((" "));}
    298         }
    299     }
    300     return(ERR_CODE_NONE);
    301 }
    302 
    303 err_code_t blackhawk_tsc_display_eye_scan_header(int8_t i) {
    304 int8_t x;
    305     EFUN_PRINTF(("\n"));
    306     EFUN_PRINTF((" Each character N represents approximate error rate 1e-N at that location\n"));
    307     for(x=1;x<=i;x++) {
    308         EFUN_PRINTF(("  UI/64  : -30  -25  -20  -15  -10  -5    0    5    10   15   20   25   30"));
    309     }
    310     EFUN_PRINTF(("\n"));
    311     for(x=1;x<=i;x++) {
    312         EFUN_PRINTF(("         : -|----|----|----|----|----|----|----|----|----|----|----|----|-"));
    313     }
    314     EFUN_PRINTF(("\n"));
    315     return(ERR_CODE_NONE);
    316 }
    317 
    318 err_code_t blackhawk_tsc_display_eye_scan_footer(int8_t i) {
    319 int8_t x;
    320     for(x=1;x<=i;x++) {
    321         EFUN_PRINTF(("         : -|----|----|----|----|----|----|----|----|----|----|----|----|-"));
    322     }
    323     EFUN_PRINTF(("\n"));
    324     for(x=1;x<=i;x++) {
    325         EFUN_PRINTF(("  UI/64  : -30  -25  -20  -15  -10  -5    0    5    10   15   20   25   30"));
    326     }
    327     EFUN_PRINTF(("\n"));
    328     return(ERR_CODE_NONE);
    329 }
    330 
    331 
    332 err_code_t blackhawk_tsc_read_eye_scan_status(srds_access_t *sa__, uint16_t *status) {
    333 
    334    if(!status) {
    335         return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    336     }
    337 
    338    ESTM(*status=rdv_usr_diag_status());
    339 
    340     return(ERR_CODE_NONE);
    341 }
    342 
    343 
    344 err_code_t blackhawk_tsc_meas_eye_scan_done(srds_access_t *sa__) {
    345   EFUN(blackhawk_tsc_pmd_uc_diag_cmd(sa__, CMD_UC_DIAG_DISABLE,GRACEFUL_STOP_TIME));
    346   return(ERR_CODE_NONE);
    347 }
    348 
    349 
    350 err_code_t blackhawk_tsc_start_ber_scan_test(srds_access_t *sa__, uint8_t ber_scan_mode, uint8_t timer_control, uint8_t max_error_control) {
    351     uint8_t lock,sts;
    352     ESTM(lock = rd_pmd_rx_lock());
    353     if(lock == 0) {
    354         EFUN_PRINTF(("Error: No PMD_RX_LOCK on lane requesting BER scan\n"));
    355         return(ERR_CODE_DIAG_SCAN_NOT_COMPLETE);
    356     }
    357     ESTM(sts =rdv_usr_sts_micro_stopped());
    358     if(sts > 1) {
    359        EFUN_PRINTF(("Error: Lane is busy (%d) requesting BER scan\n",sts));
    360         return(ERR_CODE_DIAG_SCAN_NOT_COMPLETE);
    361     }
    362 
    363     EFUN(wrcv_diag_max_time_control(timer_control));
    364     EFUN(wrcv_diag_max_err_control(max_error_control));
    365     EFUN(blackhawk_tsc_pmd_uc_cmd(sa__, CMD_CAPTURE_BER_START, ber_scan_mode,GRACEFUL_STOP_TIME));
    366     return(ERR_CODE_NONE);
    367 }
    368 
    369 err_code_t blackhawk_tsc_read_ber_scan_data(srds_access_t *sa__, uint32_t *errors, uint32_t *timer_values, uint8_t *cnt, uint32_t timeout) {
    370     uint8_t i,prbs_byte,prbs_multi,time_byte,time_multi;
    371     uint16_t sts,dataword;
    372 
    373 
    374     if(!errors || !timer_values || !cnt) {
    375         return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    376     }
    377     /* init data arrays */
    378     for(i=0;i< DIAG_MAX_SAMPLES;i++) {
    379         errors[i]=0;
    380         timer_values[i]=0;
    381     }
    382     /* Check for completion read ln.diag_status byte?*/
    383  ESTM(sts = rdv_usr_diag_status());
    384     if((sts & 0x8000) == 0) {
    385         return(blackhawk_tsc_error(sa__, ERR_CODE_DATA_NOTAVAIL));
    386     }
    387     *cnt = (sts & 0x00FF)/3;
    388     for(i=0;i < *cnt;i++) {
    389         /* Read 2 bytes of data */
    390         EFUN(blackhawk_tsc_pmd_uc_cmd(sa__, CMD_READ_DIAG_DATA_WORD, 0, timeout));
    391         ESTM(dataword = rd_uc_dsc_data());           /* LSB contains 2 -4bit nibbles */
    392         time_byte = (uint8_t)(dataword>>8);          /* MSB is time byte */
    393         prbs_multi = (uint8_t)dataword & 0x0F;       /* split nibbles */
    394         time_multi = (uint8_t)dataword>>4;
    395         /* Read 1 bytes of data */
    396         EFUN(blackhawk_tsc_pmd_uc_cmd(sa__, CMD_READ_DIAG_DATA_BYTE, 0, timeout));
    397         ESTM(prbs_byte = (uint8_t)rd_uc_dsc_data());
    398         errors[i] = blackhawk_tsc_INTERNAL_float12_to_uint32(prbs_byte,prbs_multi); /* convert 12bits to uint32 */
    399         timer_values[i] = (blackhawk_tsc_INTERNAL_float12_to_uint32(time_byte,time_multi)<<3);
    400     /*  EFUN_PRINTF(("Err=%d (%02x<<%d); Time=%d (%02x<<%d)\n",errors[i],prbs_byte,prbs_multi,timer_values[i],time_byte,time_multi<<3)); */
    401         /*if(timer_values[i] == 0 && errors[i] == 0) break;*/
    402     }
    403 
    404   return(ERR_CODE_NONE);
    405 }
    406 
    407 
    408 /* This is good example function to do BER extrapolation */
    409 err_code_t blackhawk_tsc_eye_margin_proj(srds_access_t *sa__, USR_DOUBLE rate, uint8_t ber_scan_mode, uint8_t timer_control, uint8_t max_error_control) {
    410     uint32_t errs[DIAG_MAX_SAMPLES];
    411     uint32_t time[DIAG_MAX_SAMPLES];
    412     uint8_t i,cnt=0;
    413     uint16_t sts;
    414     int16_t offset_start;
    415     /* Below 'DIAG_VERBOSE' level is intended to be modified only within a debug */
    416     /* session immediately after a breakpoint, and to retain its state only */
    417     /* through function exit:  therefore it must be 'volatile' to prevent a */
    418     /* compiler from eliding code conditioned on it, but NOT 'static'.      */
    419 
    420 
    421     for(i=0;i<DIAG_MAX_SAMPLES;i++) {
    422         errs[i]=0;
    423         time[i]=0;
    424     }
    425     /* start UC acquisition */
    426     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("start begin\n"));
    427     EFUN(blackhawk_tsc_start_ber_scan_test(sa__, ber_scan_mode, timer_control, max_error_control));
    428     ESTM(offset_start = rd_uc_dsc_data());
    429     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("offset_start = %d:%dmV\n",offset_start,blackhawk_tsc_INTERNAL_ladder_setting_to_mV(sa__, (int8_t)offset_start,0)));
    430     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("start done\n"));
    431 
    432     /* This wait is VERY LONG and should be replaced with interupt or something */
    433     if(DIAG_VERBOSE > 5) {
    434         do {
    435           EFUN(USR_DELAY_US(2000000));
    436             ESTM(sts = rdv_usr_diag_status());
    437             EFUN_PRINTF(("sts=%04x\n",sts));
    438 
    439         } while ((sts & 0x8000) == 0);
    440     } else {
    441         EFUN_PRINTF(("Waiting for measurement time approx %d seconds",timer_control+(timer_control>>1)));
    442         EFUN(blackhawk_tsc_INTERNAL_poll_diag_done(sa__, &sts,timer_control*2000));
    443     }
    444     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("delay done\n"));
    445 
    446     EFUN(blackhawk_tsc_read_ber_scan_data(sa__, &errs[0], &time[0], &cnt, 2000));
    447 
    448     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("read done cnt=%d\n",cnt));
    449 
    450     EFUN(blackhawk_tsc_pmd_uc_cmd(sa__, CMD_CAPTURE_BER_END,0x00,200));
    451 
    452     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("end function done\n"));
    453  /* if(cnt == 1) {                                                     */
    454  /*     EFUN_PRINTF(("Not enough points found to extrapolate BER\n")); */
    455  /*     return(ERR_CODE_NONE);                                         */
    456  /* }                                                                  */
    457 
    458     EFUN(blackhawk_tsc_display_ber_scan_data(sa__, rate, ber_scan_mode, &errs[0], &time[0],(uint8_t)SRDS_ABS(offset_start)));
    459 
    460     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("display done\n"));
    461 
    462     return(ERR_CODE_NONE);
    463 }
    464 
    465 
    466 
    467 err_code_t blackhawk_tsc_display_ber_scan_data (srds_access_t *sa__, USR_DOUBLE rate, uint8_t ber_scan_mode, uint32_t *total_errs, uint32_t *total_time, uint8_t max_offset) {
    468 
    469 #ifdef SERDES_API_FLOATING_POINT
    470     /* 'margins_mv[]' vector maps the p1 threshold code with actual mV
    471         Only relevant when mode=0
    472         This is not totally linear: for code 0~25 step=6mV; code 25~30 step=18mV; code 30~31 step=12
    473         'margins_mv[]' is valid only for Merlin. This vector would need to be modified accordingly for different Serdes
    474     USR_DOUBLE margins_mv[] = {0,6,12,18,24,30,36,42,48,54,60,66,72,78,84,
    475                            90,96,102,108,114,120,126,132,138,144,150,168,186,204,222,240,252};
    476     const USR_DOUBLE narrow_margins_mv[] = {0,3.6,7.2,10.8,14.4,18,21.6,25.5,28.8,32.4,36,39.6,43.2,46.8,50.4,
    477                                         54,57.6,61.2,64.8,68.4,72,75.6,79.2,82.8,86.4,90,100.8,111.6,122.4,133.2,144,151.2}; */
    478 
    479     const unsigned int HI_CONFIDENCE_ERR_CNT = 100;      /* bit errors */
    480     const unsigned int HI_CONFIDENCE_MIN_ERR_CNT = 20;   /* bit errors */
    481     const unsigned int MAX_CLIPPED_ERR_CNT = 8355840;
    482     const USR_DOUBLE ARTIFICIAL_BER = 0.5;  /* used along ARTIFICIAL_MARGIN(_V/_H) when not enough points to extrapolate */
    483     const int ARTIFICIAL_MARGIN_V = 500;    /* Used along ARTIFICIAL_BER when not enough points to extrapolate. Unit: mV. Based on the concept of max Vpp of 1 Volt */
    484     const int ARTIFICIAL_MARGIN_H = 1;  /* Used along ARTIFICIAL_BER when not enough points to extrapolate. Unit: UI. Based on the concept of two consecutive scrambled bits (1 UI appart) being uncorrelated */
    485     const int MIN_BER_TO_REPORT = -24;   /* we clip the projected BER using this number */
    486     const USR_DOUBLE MIN_BER_FOR_FIT = -8.0;    /*  all points with BER <= 10^MIN_BER_FOR_FIT will be used for line fit (i.e used for extrapolation) */
    487 
    488     /* BER confidence scale */
    489     const USR_DOUBLE ber_conf_scale[104] = {
    490         2.9957,5.5717,3.6123,2.9224,2.5604,2.3337,2.1765,2.0604,1.9704,1.8983,
    491         1.8391,1.7893,1.7468,1.7100,1.6778,1.6494,1.6239,1.6011,1.5804,1.5616,
    492         1.5444,1.5286,1.5140,1.5005,1.4879,1.4762,1.4652,1.4550,1.4453,1.4362,
    493         1.4276,1.4194,1.4117,1.4044,1.3974,1.3908,1.3844,1.3784,1.3726,1.3670,
    494         1.3617,1.3566,1.3517,1.3470,1.3425,1.3381,1.3339,1.3298,1.3259,1.3221,
    495         1.3184,1.3148,1.3114,1.3080,1.3048,1.3016,1.2986,1.2956,1.2927,1.2899,
    496         1.2872,1.2845,1.2820,1.2794,1.2770,1.2746,1.2722,1.2700,1.2677,1.2656,
    497         1.2634,1.2614,1.2593,1.2573,1.2554,1.2535,1.2516,1.2498,1.2481,1.2463,
    498         1.2446,1.2429,1.2413,1.2397,1.2381,1.2365,1.2350,1.2335,1.2320,1.2306,
    499         1.2292,1.2278,1.2264,1.2251,1.2238,1.2225,1.2212,1.2199,1.2187,1.2175,
    500         1.2163, /* starts in index: 100 for #errors: 100,200,300,400 */
    501         1.1486, /* 200 */
    502         1.1198, /* 300 */
    503         1.1030};    /*400 */
    504 
    505 
    506     /* Define variables */
    507     USR_DOUBLE lbers[DIAG_MAX_SAMPLES] = {0};       /* Internal linear scale sqrt(-log(ber)) */
    508     USR_DOUBLE margins[DIAG_MAX_SAMPLES] = {0};     /* Eye margin @ each measurement */
    509     USR_DOUBLE bers[DIAG_MAX_SAMPLES] = {0};        /* computed bit error rate */
    510     uint32_t i;
    511     int8_t offset[DIAG_MAX_SAMPLES];
    512     int8_t mono_flags[DIAG_MAX_SAMPLES];
    513 
    514     int8_t direction;
    515     uint8_t heye;
    516     int8_t delta_n=1;
    517     USR_DOUBLE Exy = 0.0;
    518     USR_DOUBLE Eyy = 0.0;
    519     USR_DOUBLE Exx = 0.0;
    520     USR_DOUBLE Ey  = 0.0;
    521     USR_DOUBLE Ex  = 0.0;
    522     USR_DOUBLE alpha = 0.0;
    523     USR_DOUBLE gauss_noise = -1;
    524     USR_DOUBLE beta = 0.0;
    525     USR_DOUBLE sq_r = 0.0, alpha2 = 0.0;
    526     USR_DOUBLE proj_ber = 0.0, proj_ber_aux = 0.0;
    527     USR_DOUBLE proj_margin_12 = 0.0;
    528     USR_DOUBLE proj_margin_15 = 0.0;
    529     USR_DOUBLE proj_margin_18 = 0.0;
    530     USR_DOUBLE sq_err1 = 0.0, sq_err2 = 0.0;
    531     USR_DOUBLE ierr;
    532     uint8_t start_n;
    533     uint8_t stop_n;
    534     uint8_t low_confidence=1;
    535     uint8_t loop_index;
    536     uint8_t n_mono = 0;
    537     uint8_t eye_cnt;
    538     uint8_t hi_confidence_cnt = 0;
    539     int8_t first_good_ber_idx = -1;
    540     int8_t first_small_errcnt_idx = -1;
    541     int8_t first_non_clipped_errcnt_idx = -1;
    542     uint8_t range250;
    543     uint8_t intrusive;
    544     uint8_t ber_clipped = 0;
    545     uint8_t last_point_discard;
    546     uint8_t fit_count;
    547     int artificial_margin;
    548     int proj_case = 0;  /* this variable will be used to signal what particular extrapolation case has happened at the end (after discarding invalid points of all sorts). To avoid potential issues: NEVER RE-USE VALUES... new cases should receive brand-new integer value */
    549     USR_DOUBLE artificial_lber;
    550     char message[256] = "NO MESSAGE";
    551     char unit[5];
    552 
    553     if(!total_errs || !total_time ) {
    554         return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    555     }
    556 
    557     /* Initialize BER array */
    558     for (i = 0; i < DIAG_MAX_SAMPLES; i++) {
    559         bers[i] = 0;
    560         mono_flags[i] = 0;
    561     }
    562 
    563     /* Decode mode/direction/etc. */
    564     heye = (ber_scan_mode & DIAG_BER_HORZ)>>1;
    565     direction = (ber_scan_mode & DIAG_BER_NEG) ? -1 : 1 ;
    566     range250 = (ber_scan_mode & DIAG_BER_P1_NARROW) ? 0 : 1;
    567     intrusive = (ber_scan_mode & DIAG_BER_INTR) ? 1 : 0;
    568 
    569     /* Prepare artificial points in case they are needed */
    570     if (heye == 1) {
    571         artificial_margin = direction*ARTIFICIAL_MARGIN_H;
    572     } else {
    573         artificial_margin = direction*ARTIFICIAL_MARGIN_V;
    574     }
    575     artificial_lber = (USR_DOUBLE)sqrt(-log10(ARTIFICIAL_BER));
    576 
    577     /* Printing on-screen message */
    578     if (heye == 1) {
    579         if (direction==-1) EFUN_PRINTF(("\n\n********** HORIZONTAL PROJECTION: LEFT SIDE ******************\n"));
    580         if (direction== 1) EFUN_PRINTF(("\n\n********** HORIZONTAL PROJECTION: RIGHT SIDE *****************\n"));
    581     } else {
    582         if (direction==-1) EFUN_PRINTF(("\n\n********** VERTICAL PROJECTION: BOTTOM ***********************\n"));
    583         if (direction== 1) EFUN_PRINTF(("\n\n********** VERTICAL PROJECTION: TOP **************************\n"));
    584     }
    585 
    586     /* *******************************************
    587         * Generate margins[]
    588         * Generate ber[]
    589         * Find first and last points for linear fit
    590  */
    591     i=0;
    592     do {
    593         if(heye == 1) {
    594             ENULL_STRCPY(unit,"mUI");
    595             offset[i] = (int8_t)(max_offset-i*2);
    596 #ifndef STANDALONE_EVENT
    597             margins[i] = direction*offset[i]*1000.0/128.0;
    598 #else
    599             margins[i] = info_out->margins[i];
    600 #endif
    601         } else {
    602             ENULL_STRCPY(unit,"mV");
    603             offset[i] = (int8_t)(max_offset-i);
    604 #ifndef STANDALONE_EVENT
    605             if(intrusive) {
    606                 
    607                 margins[i] = direction*blackhawk_tsc_INTERNAL_ladder_setting_to_mV(sa__, offset[i], 0);
    608             } else {
    609                 margins[i] = direction*blackhawk_tsc_INTERNAL_ladder_setting_to_mV(sa__, offset[i], range250);
    610             }
    611 #else
    612             margins[i] = info_out->margins[i];
    613 #endif
    614         }
    615         if (total_errs[i] == 0) {
    616             bers[i] = 1.0/(((USR_DOUBLE)total_time[i])*0.00001*rate);
    617         } else {
    618             bers[i] = (USR_DOUBLE)total_errs[i]/(((USR_DOUBLE)total_time[i])*0.00001*rate);
    619         }
    620 
    621         /* Find the first data point with good BER (BER <= 10^MIN_BER_FOR_FIT)
    622         NOTE: no need for lower bound on BER, since correction factors will be applied for all total_errs>=0 */
    623         if ((log10(bers[i]) <= MIN_BER_FOR_FIT) && (first_good_ber_idx == -1)) {
    624             first_good_ber_idx = (int8_t)i;
    625         }
    626 
    627         /* Determine high-confidence iterations */
    628         if (total_errs[i] >= HI_CONFIDENCE_ERR_CNT) {
    629             hi_confidence_cnt++;
    630         } else if ((total_errs[i] < HI_CONFIDENCE_MIN_ERR_CNT) && (first_small_errcnt_idx == -1)) {
    631             /* find the first data point with small error count */
    632             first_small_errcnt_idx = (int8_t)i;
    633         }
    634 
    635         /* Determine first NON-clipped error count
    636             NOTE: Originally this limit was created for post processing of micro-generated data; however, this could be used for PC-generated data as well */
    637         if ((total_errs[i] < MAX_CLIPPED_ERR_CNT) && (first_non_clipped_errcnt_idx == -1) ) {
    638             first_non_clipped_errcnt_idx = (int8_t)i;
    639         }
    640 
    641       i++;
    642 
    643     } while(((total_errs[i] != 0) || (total_time[i] != 0)) && (i<=max_offset));
    644 
    645     eye_cnt = (int8_t) i;
    646 
    647 
    648     /* *******************************************
    649     Setting up stop_n variable.
    650     Check if:
    651         - There is only one point in measurement vector (i.e. eye_cnt = 1)
    652         - The very last point's measurement time was "too short"
    653  */
    654 
    655     i = eye_cnt - 1;
    656     if (i>=1) {
    657         if ((total_time[i] >= 0.5*total_time[i-1]) || (total_errs[i] >= HI_CONFIDENCE_MIN_ERR_CNT) ){
    658             stop_n = eye_cnt;   /* last point will be included in linear fit */
    659             last_point_discard = 0;
    660         } else {
    661             stop_n = eye_cnt - 1;   /* discards the very last point */
    662             last_point_discard = 1;
    663         }
    664     } else {
    665         stop_n = 1; /* there is ONLY one measurement */
    666         last_point_discard = 0;
    667     }
    668 
    669 
    670     /* *******************************************
    671     Print on screen (prints RAW BER data. i.e. conf factors)
    672  */
    673     i = 0;
    674     do {
    675         if (total_errs[i] == 0) {
    676            EFUN_PRINTF(("BER @ %4.0f %s < 1e%-6.2f (%u errors in %0.2f sec)\n", margins[i], unit, log10(bers[i]), total_errs[i], ((USR_DOUBLE)total_time[i])*0.00001));
    677         } else if (total_errs[i] >= MAX_CLIPPED_ERR_CNT) {
    678            EFUN_PRINTF(("BER @ %4.0f %s > 1e%-6.2f (%u errors in %0.2f sec)\n", margins[i], unit, log10(bers[i]), total_errs[i], ((USR_DOUBLE)total_time[i])*0.00001));
    679         } else {
    680            EFUN_PRINTF(("BER @ %4.0f %s = 1e%-6.2f (%u errors in %0.2f sec)\n", margins[i], unit, log10(bers[i]), total_errs[i], ((USR_DOUBLE)total_time[i])*0.00001));
    681         }
    682         i++;
    683     } while (i<stop_n);
    684 
    685     /* *******************************************
    686     Correcting *all* BER values using confidence factors in 'ber_conf_scale' vector
    687     This step is done for extrapolation purposes
    688  */
    689     for (loop_index=0; loop_index < eye_cnt; loop_index++) {
    690         if (total_errs[loop_index] <= 100) {
    691             bers[loop_index] = ber_conf_scale[total_errs[loop_index]] * bers[loop_index];
    692         } else if (total_errs[loop_index] > 100 && total_errs[loop_index] < 200) {
    693             bers[loop_index] = ber_conf_scale[100] * bers[loop_index];
    694         } else if (total_errs[loop_index] >= 200 && total_errs[loop_index] < 300) {
    695             bers[loop_index] = ber_conf_scale[101] * bers[loop_index];
    696         } else if (total_errs[loop_index] >= 300 && total_errs[loop_index] < 400) {
    697             bers[loop_index] = ber_conf_scale[102] * bers[loop_index];
    698         } else if (total_errs[loop_index] >= 400) {
    699             bers[loop_index] = ber_conf_scale[103] * bers[loop_index];
    700         }
    701     }
    702 
    703     /* *******************************************
    704     Computes the "linearised" ber vector
    705  */
    706     for (loop_index=0; loop_index<eye_cnt; loop_index++) {
    707         lbers[loop_index] = (USR_DOUBLE)sqrt(-log10(bers[loop_index]));
    708     }
    709 
    710     /* *******************************************
    711     Assign highest data point to use
    712  */
    713     if (first_good_ber_idx == -1) {
    714         start_n = stop_n;
    715     } else {
    716         start_n = first_good_ber_idx;
    717     }
    718 
    719 
    720 
    721     /* ******************************************************
    722     ***********  EXTRAPOLATION (START) **********************
    723     *********************************************************
    724     Different data set profiles can be received by this code.
    725     Each case is processed accordingly here (IF-ELSE IF cases)
    726  */
    727 
    728     /* ====> Errors encountered all the way to sampling point */
    729     if (start_n >= eye_cnt) {
    730         proj_case = 1;
    731         ENULL_STRCPY(message,"No low-BER point measured");
    732 
    733         /* confidence factor of 0.96 is applied in this case to set a LOWER bound and report accordingly.
    734             This factor corresponds to approximately 3000 errors @95% confidence
    735             For reference: factors for 900, 2000, 3000, 5000, 20000 and 50000 errors are: 0.96, 0.96, 0.97, 0.99, 0.99, respectively */
    736         proj_ber = 0.96*log10(bers[eye_cnt-1]);
    737         proj_ber_aux = proj_ber;
    738         EFUN_PRINTF(("BER *worse* than 1e%0.2f\n", proj_ber));
    739         EFUN_PRINTF(("No margin @ 1e-12, 1e-15 & 1e-18\n\n\n"));
    740         fit_count = 1;
    741     }
    742 
    743     else {
    744 
    745         /* ====> Only ONE measured point. Typically when the eye is wide open.
    746             Artificial points will be used to make extrapolation possible */
    747         if (stop_n==1) {
    748             proj_case = 2;
    749             ENULL_STRCPY(message,"Not enough points (single measured point). Using artificial point");
    750 
    751             low_confidence = 1;
    752             delta_n = 1;    /* 'delta_n' and 'fit_count' variables were kept for future use in case a new approach to handle low confidence case is adopted */
    753             fit_count = 2;
    754 
    755             /* Compute covariances and means... but only for two points: artificial and the single measured point */
    756             Exy = ((margins[0]*lbers[0] + artificial_margin*artificial_lber)/2.0);
    757             Eyy = ((lbers[0]*lbers[0] + artificial_lber*artificial_lber)/2.0);
    758             Exx = ((margins[0]*margins[0] + artificial_margin*artificial_margin)/2.0);
    759             Ey  = ((lbers[0] + artificial_lber)/2.0);
    760             Ex  = ((margins[0] + artificial_margin)/2.0);
    761         }
    762 
    763         /* ====> "NORMAL" case (when there are more than 1 measurements) */
    764         else {
    765 
    766             /* Detect and record nonmonotonic data points */
    767             for (loop_index=0; loop_index < stop_n; loop_index++) {
    768                 if ((loop_index > start_n) && (log10(bers[loop_index]) > log10(bers[loop_index-1]))) {
    769                     mono_flags[loop_index] = 1;
    770                     if (first_good_ber_idx != -1) {
    771                         n_mono++;
    772                     }
    773                 }
    774             }
    775 
    776             /* Finds number of MEASURED points available for extrapolation */
    777             delta_n = (stop_n-start_n-n_mono);
    778 
    779 
    780             /*  HIGH CONFIDENCE case */
    781 
    782             if (delta_n >= 2) { /* there are at least 2 points to trace a line */
    783                 proj_case = 3;
    784                 ENULL_STRCPY(message,"Normal case");
    785                 low_confidence = 0;
    786 
    787                 /* Compute covariances and means */
    788                 fit_count = 0;
    789                 for (loop_index=start_n; loop_index < stop_n; loop_index++) {
    790                     if (mono_flags[loop_index] == 0) {
    791                         Exy += (margins[loop_index]*lbers[loop_index]/(USR_DOUBLE)delta_n);
    792                         Eyy += (lbers[loop_index]*lbers[loop_index]/(USR_DOUBLE)delta_n);
    793                         Exx += (margins[loop_index]*margins[loop_index]/(USR_DOUBLE)delta_n);
    794                         Ey  += (lbers[loop_index]/(USR_DOUBLE)delta_n);
    795                         Ex  += (margins[loop_index]/(USR_DOUBLE)delta_n);
    796                         fit_count++;
    797                     }
    798                 }
    799             }
    800 
    801             /*  LOW CONFIDENCE case */
    802 
    803             else {  /*  NEW APPROACH (08/28/2014): consider very first point (error count < MAX_CLIPPED_ERR_CNT) and very last point for linear fit. This will give pessimistic/conservative extrapolation */
    804                 low_confidence = 1;
    805                 if ( (first_non_clipped_errcnt_idx>=0) && (first_non_clipped_errcnt_idx < start_n)) {
    806                     proj_case = 4;
    807                     ENULL_STRCPY(message,"Not enough points. Using first measured point for conservative estimation");
    808                     fit_count = 2;
    809                     /* Compute covariances and means... but only for two points: first and last */
    810                     Exy = ((margins[stop_n-1]*lbers[stop_n-1] + margins[first_non_clipped_errcnt_idx]*lbers[first_non_clipped_errcnt_idx])/2.0);
    811                     Eyy = ((lbers[stop_n-1]*lbers[stop_n-1] + lbers[first_non_clipped_errcnt_idx]*lbers[first_non_clipped_errcnt_idx])/2.0);
    812                     Exx = ((margins[stop_n-1]*margins[stop_n-1] + margins[first_non_clipped_errcnt_idx]*margins[first_non_clipped_errcnt_idx])/2.0);
    813                     Ey  = ((lbers[stop_n-1] + lbers[first_non_clipped_errcnt_idx])/2.0);
    814                     Ex  = ((margins[stop_n-1] + margins[first_non_clipped_errcnt_idx])/2.0);
    815                 } else {
    816                     proj_case = 5;
    817                     ENULL_STRCPY(message,"Not enough points (cannot use non-clipped ErrorCount point). Using artificial point");
    818                     /* Compute covariances and means... but only for two points: artificial and the single measured point */
    819                     Exy = (artificial_margin*artificial_lber)/2.0;
    820                     Eyy = (artificial_lber*artificial_lber)/2.0;
    821                     Exx = (artificial_margin*artificial_margin)/2.0;
    822                     Ey  = (artificial_lber)/2.0;
    823                     Ex  = (artificial_margin)/2.0;
    824                     fit_count = 1;
    825                     /* This FOR loop checks for monotonicity as well */
    826                     for (loop_index=start_n; loop_index < stop_n; loop_index++) {
    827                         if (mono_flags[loop_index] == 0) {
    828                             Exy += (margins[loop_index]*lbers[loop_index]/2.0);
    829                             Eyy += (lbers[loop_index]*lbers[loop_index]/2.0);
    830                             Exx += (margins[loop_index]*margins[loop_index]/2.0);
    831                             Ey  += (lbers[loop_index]/2.0);
    832                             Ex  += (margins[loop_index]/2.0);
    833                             fit_count++;
    834                         }
    835                     }
    836                 }
    837             }
    838         }
    839 
    840         /* Compute fit slope and offset: ber = alpha*margin + beta */
    841         alpha = (Exy - Ey*Ex) / (Exx - Ex*Ex);
    842         beta = Ey - Ex*alpha;
    843         /* Compute alpha2: slope of regression: margin = alpha2*ber + beta2 */
    844         alpha2 = (Exy - Ey*Ex) / (Eyy - Ey*Ey);
    845         /* Compute correlation index sq_r */
    846         sq_r = alpha*alpha2;
    847 
    848         proj_ber = pow(10,(-beta*beta));
    849         proj_margin_12 = direction*(sqrt(-log10(1e-12))-beta)/alpha;
    850         proj_margin_15 = direction*(sqrt(-log10(1e-15))-beta)/alpha;
    851         proj_margin_18 = direction*(sqrt(-log10(1e-18))-beta)/alpha;
    852 
    853         /* Estimate modeled gaussian noise.
    854 
    855             The following is based on the Q-function model and the following table:
    856                 Q    |    log10(BER)
    857             =======================
    858               7.033    |    -12
    859               7.941    |    -15
    860               8.757    |    -18
    861 
    862         Based on the above, we solve for sigma:
    863             7.033*sigma = u - proj_margin_12 , and
    864             7.941*sigma = u - proj_margin_15
    865         */
    866         gauss_noise = (proj_margin_12 - proj_margin_15)/0.908;
    867 
    868         sq_err1 = (Eyy + (beta*beta) + (Exx*alpha*alpha) -
    869                    (2*Ey*beta) - (2*Exy*alpha) + (2*Ex*beta*alpha));
    870         sq_err2 = 0;
    871         for (loop_index=start_n; loop_index<stop_n; loop_index++) {
    872             ierr = (lbers[loop_index] - (alpha*margins[loop_index] + beta));
    873             sq_err2 += (ierr*ierr/(USR_DOUBLE)delta_n);
    874         }
    875 
    876         proj_ber = log10(proj_ber);
    877         proj_ber_aux = proj_ber;
    878 
    879         if (proj_ber < MIN_BER_TO_REPORT) {
    880             proj_ber = MIN_BER_TO_REPORT;
    881             ber_clipped = 1;
    882         }
    883 
    884         /* Extrapolated results, low confidence */
    885         if (low_confidence == 1) {
    886 
    887             EFUN_PRINTF(("BER(extrapolated) < 1e%0.2f\n", proj_ber));
    888             EFUN_PRINTF(("Margin @ 1e-12    > %0.2f %s\n", (proj_ber < -12)? SRDS_ABS(proj_margin_12) : 0, unit));
    889             EFUN_PRINTF(("Margin @ 1e-15    > %0.2f %s\n", (proj_ber < -15)? SRDS_ABS(proj_margin_15) : 0, unit));
    890             EFUN_PRINTF(("Margin @ 1e-18    > %0.2f %s\n", (proj_ber < -18)? SRDS_ABS(proj_margin_18) : 0, unit));
    891 
    892         /* Extrapolated results, HIGH confidence */
    893         } else {
    894 
    895             if (ber_clipped == 1) {
    896                 EFUN_PRINTF(("BER(extrapolated) < 1e%0.2f\n", proj_ber));
    897             } else {
    898                 EFUN_PRINTF(("BER(extrapolated) = 1e%0.2f\n", proj_ber));
    899             }
    900             EFUN_PRINTF(("Margin @ 1e-12    = %0.2f %s\n", (proj_ber < -12)? SRDS_ABS(proj_margin_12) : 0, unit));
    901             EFUN_PRINTF(("Margin @ 1e-15    = %0.2f %s\n", (proj_ber < -15)? SRDS_ABS(proj_margin_15) : 0, unit));
    902             EFUN_PRINTF(("Margin @ 1e-18    = %0.2f %s\n", (proj_ber < -18)? SRDS_ABS(proj_margin_18) : 0, unit));
    903         }
    904 
    905         EFUN_PRINTF(("\n\n"));
    906 
    907         /* Print non-monotonic outliers */
    908         if (n_mono != 0) {
    909             EFUN_PRINTF(("Detected non-monotonicity at { "));
    910             for (loop_index = start_n; loop_index < stop_n; loop_index++) {
    911                 if (mono_flags[loop_index] == 1) {
    912                     EFUN_PRINTF(("%0.2f ", margins[loop_index]));
    913                 }
    914             }
    915             EFUN_PRINTF(("} %s\n\n\n",unit));
    916         }
    917 
    918     }
    919     /* *******************************************
    920     ***********  EXTRAPOLATION (END) *************
    921  */
    922 
    923 
    924 
    925     /* SUMMARY (for debugging purposes */
    926     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("\t=====> DEBUG INFO (start)\n\n"));
    927     if (DIAG_VERBOSE > 2) {
    928         EFUN_PRINTF((" loop   Margin      total_errors   time(sec)  logBER       lber"));
    929         for (loop_index=0; loop_index < stop_n+last_point_discard; loop_index++) {
    930             EFUN_PRINTF(("\n%5d %11.0f %14d %10.3f %8.2f %10.3f", loop_index, margins[loop_index], total_errs[loop_index], ((USR_DOUBLE)total_time[loop_index])*0.00001, log10(bers[loop_index]), lbers[loop_index]));
    931         }
    932         EFUN_PRINTF(("\n\n"));
    933     }
    934     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("Max Offset = %d\n",max_offset));
    935     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("ber_clipped: %d, Projected BER (proj_ber_aux) = %.2f\n", ber_clipped, proj_ber_aux));
    936     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("first good ber idx at %d, ber = 1e%f\n", first_good_ber_idx, ((first_good_ber_idx>=0) ? log10(bers[first_good_ber_idx]) : 0.0)));
    937     {
    938         char aux_str[20];
    939         USR_SPRINTF(aux_str, "%d", total_errs[first_small_errcnt_idx]);
    940         if (DIAG_VERBOSE > 2) EFUN_PRINTF(("first small errcnt idx at %d, errors = %s\n", first_small_errcnt_idx, ((first_small_errcnt_idx>=0) ? aux_str : "-1")));
    941     }
    942     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("last point discarded?: %d, low_confidence: %d, first_non_clipped_errcnt_idx: %d, start_n: %d, stop_n: %d, eye_cnt: %d, n_mono: %d, first_good_ber_idx = %d, first_small_errcnt_idx = %d, fit_count: %d, delta_n: %d\n",
    943                 last_point_discard, low_confidence, first_non_clipped_errcnt_idx, start_n, stop_n, eye_cnt, n_mono, first_good_ber_idx, first_small_errcnt_idx, fit_count, delta_n));
    944     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("Exy=%.2f, Eyy=%.4f, Exx=%.2f, Ey=%.4f, Ex=%.2f, alpha=%.4f, beta=%.4f, alpha2=%.3f, sq_r=%.3f, sq_err1=%g, sq_err2=%g, gauss_noise=%.3f\n", Exy,Eyy,Exx,Ey,Ex,alpha,beta,alpha2,sq_r,sq_err1,sq_err2,gauss_noise));
    945     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("%s\n", message));
    946     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("proj_case %d\n",proj_case));
    947     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("\n\t=====> DEBUG INFO (end)\n\n"));
    948     EFUN_PRINTF(("\n\n\n"));
    949 
    950 
    951 #else
    952     UNUSED(rate);
    953     UNUSED(ber_scan_mode);
    954     UNUSED(max_offset);
    955 
    956     EFUN_PRINTF(("This function needs SERDES_API_FLOATING_POINT define to operate \n"));
    957 
    958     if(!total_errs || !total_time ) {
    959         return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    960     }
    961 #endif
    962     return(ERR_CODE_NONE);
    963 }
    964 
    965 /*****************************/
    966 /*  Display Lane/Core State  */
    967 /*****************************/
    968 
    969 err_code_t blackhawk_tsc_display_lane_state_hdr(void) {
    970   EFUN_PRINTF(("LN (RX  , CDRxN , UC_CFG,UC_STS,TX_RX_RST,STP,PLL)  "));
    971   EFUN_PRINTF(("SD LCK RXPPM "));
    972   EFUN_PRINTF(("CLK90 "));
    973   EFUN_PRINTF((" PF(MLHR)   "));
    974   EFUN_PRINTF(("VGA "));
    975   EFUN_PRINTF(("DCO P1mV "));
    976   EFUN_PRINTF(("    TP(0,1,2,3,4)    "));
    977   EFUN_PRINTF(("     DFE(1,2,3,4,5,6)   "));
    978   EFUN_PRINTF(("  TXPPM    TXEQ(n2,n1,m,p1,p2,p3)    EYE(L,R,U,D)   "));
    979   EFUN_PRINTF(("LINK_TIME   BER"));
    980   EFUN_PRINTF(("\n"));
    981   return (ERR_CODE_NONE);
    982 }
    983 
    984 err_code_t blackhawk_tsc_display_lane_state_legend(void) {
    985   EFUN_PRINTF(("\n"));
    986   EFUN_PRINTF(("**********************************************************************************************\n"));
    987   EFUN_PRINTF(("****                Legend of Entries in display_lane_state()                             ****\n"));
    988   EFUN_PRINTF(("**********************************************************************************************\n"));
    989   EFUN_PRINTF(("LN        : Lane index within IP core\n"));
    990   EFUN_PRINTF(("RX        : RX PAM mode (NRZ - NRZ; P4N - PAM4_NS; P4E - PAM4_ES)\n"));
    991   EFUN_PRINTF(("CDRxN     : CDR type x OSR ratio [xG-OSx16; xH-OSx16p5; xJ-OSx21.2; xK-OSx20p6; xW-OSx32] \n"));
    992   EFUN_PRINTF(("UC_CFG    : Micro lane configuration variable\n"));
    993   EFUN_PRINTF(("UC_STS    : Micro lane status variable\n"));
    994 #if defined(SERDES_TX_RS_SEPARATE)
    995   EFUN_PRINTF(("TX_RX_RST : TX and RX Reset State{reset_active, reset_occured, reset_held}\n"));
    996 #else
    997   EFUN_PRINTF(("RST       : Reset State{reset_active, reset_occured, reset_held}\n"));
    998 #endif
    999   EFUN_PRINTF(("STP       : uC Stopped State\n"));
   1000   EFUN_PRINTF(("PLL       : TX and RX PLL select\n"));
   1001   EFUN_PRINTF(("SD        : Signal Detect\n"));
   1002   EFUN_PRINTF(("LCK       : pmd_rx_lock\n"));
   1003   EFUN_PRINTF(("RXPPM     : Frequency offset of local reference clock with respect to RX data in ppm\n"));
   1004   EFUN_PRINTF(("CLK90     : Delay of zero crossing slicer, m1, wrt to data in PI codes\n"));
   1005   EFUN_PRINTF(("CLKP1     : Delay of diagnostic/lms slicer, p1, wrt to data in PI codes\n"));
   1006   EFUN_PRINTF(("PF(MLHR)  : Peaking Filter Main (0..15), Low Freq (0..7), High Freq (0..7), Peaking/BW Reduction settings\n"));
   1007 #if defined(RX_VGA_CTRL_VAL_MIN)
   1008   EFUN_PRINTF(("VGA       : Variable Gain Amplifier settings (%d..%d)\n", RX_VGA_CTRL_VAL_MIN, RX_VGA_CTRL_VAL_MAX));
   1009 #else
   1010   EFUN_PRINTF(("VGA       : Variable Gain Amplifier settings (0..%d)\n", RX_VGA_CTRL_VAL_MAX));
   1011 #endif
   1012   EFUN_PRINTF(("DCO       : DC offset DAC control value\n"));
   1013   EFUN_PRINTF(("P1mV      : Vertical threshold voltage of p1 slicer\n"));
   1014   EFUN_PRINTF(("TP(0,1,2,3,4):\n"));
   1015   EFUN_PRINTF(("         0 - Echos user provided 'RX_Channel_Loss_hint' in PAM4 mode, 'M1 vertical threshold voltage (mV)' in NRZ mode\n"));
   1016   EFUN_PRINTF(("         1 - Initial Channel Loss Estimate from 0-15 -- min to max within the AFE BW's operating range, negative value is an indicator of over-equalization\n"));
   1017   EFUN_PRINTF(("         2 - AFE BW, For NR mode (0 to 5 - for shortest to longest), For ER mode (0, 1 - shorter/longer)\n"));
   1018   EFUN_PRINTF(("         3 - usr_status_eq_debug1\n"));
   1019   EFUN_PRINTF(("         4 - usr_status_tp_metric_1\n"));
   1020   EFUN_PRINTF(("DFE taps  : ISI correction taps in units of 2mV\n"));
   1021   EFUN_PRINTF(("TXPPM     : Frequency offset of local reference clock with respect to TX data in ppm\n"));
   1022   EFUN_PRINTF(("TXEQ(n2,n1,m,p1,p2,p3) : TX equalization FIR tap weights in units of 1Vpp/168 for PAM4 or 1Vpp/127 for NRZ\n"));
   1023   EFUN_PRINTF(("                       : A 'P' preceding the tap weights denotes TX Precoder is enabled\n"));
   1024   EFUN_PRINTF(("                       : A 'T' preceding the tap weights denotes TX Training is enabled\n"));
   1025   EFUN_PRINTF(("EYE(L,R,U,D) : Eye margin @ 1e-5 as seen by internal diagnostic slicer in mUI and mV\n"));
   1026   EFUN_PRINTF(("LINK_TIME : Link time in milliseconds\n"));
   1027   EFUN_PRINTF(("BER : Bit Error Rate calculated based on 100ms test time; displayed only if prbs_chk_en=1.\n"));
   1028   EFUN_PRINTF(("**********************************************************************************************\n"));
   1029   return (ERR_CODE_NONE);
   1030 }
   1031 
   1032 err_code_t blackhawk_tsc_display_lane_state(srds_access_t *sa__) {
   1033   err_code_t err_code = blackhawk_tsc_INTERNAL_display_lane_state_no_newline(sa__);
   1034   EFUN_PRINTF(("\n"));
   1035   return (err_code);
   1036 }
   1037 
   1038 err_code_t blackhawk_tsc_display_core_state_hdr(void) {
   1039     char core_type[20] = "blackhawk_tsc";
   1040     COMPILER_REFERENCE(core_type);
   1041     EFUN_PRINTF(("SerDes type = %s\n",core_type));
   1042 
   1043   EFUN_PRINTF(("CORE RST_ST  PLL_PWDN  UC_ATV   COM_CLK   UCODE_VER  API_VER  AFE_VER   LIVE_TEMP   AVG_TMON   RESCAL     VCO_RATE     ANA_VCO_RANGE  PLL0_DIV PLL1_DIV PLL_LOCK"));
   1044   EFUN_PRINTF((" PLL_COMP_THRESH\n"));
   1045   return (ERR_CODE_NONE);
   1046 }
   1047 
   1048 err_code_t blackhawk_tsc_display_core_state_line(srds_access_t *sa__) {
   1049   err_code_t err_code = blackhawk_tsc_INTERNAL_display_core_state_no_newline(sa__);
   1050   EFUN_PRINTF(("\n"));
   1051   return (err_code);
   1052 }
   1053 
   1054 err_code_t blackhawk_tsc_display_core_state_legend(void) {
   1055   EFUN_PRINTF(("\n"));
   1056   EFUN_PRINTF(("**************************************************************************************************************\n"));
   1057   EFUN_PRINTF(("****                          Legend of Entries in display_core_state()                                   ****\n"));
   1058   EFUN_PRINTF(("**************************************************************************************************************\n"));
   1059   EFUN_PRINTF(("*  RST_ST           : Core Reset State PLL0{active,occured,held}, Reset State PLL1, Core uC Status byte(hex) *\n"));
   1060   EFUN_PRINTF(("*  PLL_PWDN         : PLL Powerdown Control Bit (active high)                                                *\n"));
   1061   EFUN_PRINTF(("*  UC_ATV           : UC Active bit                                                                          *\n"));
   1062   EFUN_PRINTF(("*  COM_CLK          : COM Clock frequency in MHz                                                             *\n"));
   1063   EFUN_PRINTF(("*  UCODE_VER        : Microcode Version [majorversion_minorversion]                                          *\n"));
   1064   EFUN_PRINTF(("*  API_VER          : API Version                                                                            *\n"));
   1065   EFUN_PRINTF(("*  AFE_VER          : AFE Hardware Vesrion                                                                   *\n"));
   1066   EFUN_PRINTF(("*  LIVE_TEMP        : Live Die temperature in Celsius                                                        *\n"));
   1067   EFUN_PRINTF(("*  AVG_TMON         : uC Temp_idx, Average temperature in Celsius                                            *\n"));
   1068   EFUN_PRINTF(("*  RESCAL           : Analog Resistor Calibration value                                                      *\n"));
   1069   EFUN_PRINTF(("*  VCO_RATE         : uC VCO Rate in GHz (approximate)                                                       *\n"));
   1070   EFUN_PRINTF(("*  ANA_VCO_RANGE    : Analog VCO Range                                                                       *\n"));
   1071   EFUN_PRINTF(("*  REFCLK_2x        : Refclk doubler enabler                                                                 *\n"));
   1072   EFUN_PRINTF(("*  PLL_DIV          : (Register Value) Actual PLL Divider Value                                              *\n"));
   1073   EFUN_PRINTF(("*  PLL_Lock         : PLL Lock                                                                               *\n"));
   1074 
   1075   EFUN_PRINTF(("**************************************************************************************************************\n"));
   1076   return (ERR_CODE_NONE);
   1077 }
   1078 
   1079 /**********************************************/
   1080 /*  Display Lane/Core Config and Debug Status */
   1081 /**********************************************/
   1082 err_code_t blackhawk_tsc_display_core_config(srds_access_t *sa__) {
   1083     EFUN_PRINTF(("\n\n***********************************\n"  ));
   1084     EFUN_PRINTF((    "**** SERDES CORE CONFIGURATION ****\n"  ));
   1085     EFUN_PRINTF((    "***********************************\n\n"));
   1086     {
   1087         struct   blackhawk_tsc_uc_core_config_st core_cfg;
   1088         struct   blackhawk_tsc_uc_core_config_st pll1_cfg;
   1089 
   1090         ENULL_MEMSET(&pll1_cfg, 0, sizeof(pll1_cfg));
   1091         ENULL_MEMSET(&core_cfg, 0, sizeof(core_cfg));
   1092         {
   1093             uint8_t pll_orig;
   1094             ESTM(pll_orig = blackhawk_tsc_get_pll_idx(sa__));
   1095             EFUN(blackhawk_tsc_set_pll_idx(sa__, 0));
   1096             EFUN(blackhawk_tsc_get_uc_core_config(sa__, &core_cfg));
   1097             EFUN(blackhawk_tsc_set_pll_idx(sa__, 1));
   1098             EFUN(blackhawk_tsc_get_uc_core_config(sa__, &pll1_cfg));
   1099             EFUN(blackhawk_tsc_set_pll_idx(sa__, pll_orig));
   1100         }
   1101         {
   1102             uint16_t  vco_mhz = (uint16_t)core_cfg.vco_rate_in_Mhz;
   1103             uint16_t  vco1_mhz = (uint16_t)pll1_cfg.vco_rate_in_Mhz;
   1104             COMPILER_REFERENCE(vco_mhz);
   1105             COMPILER_REFERENCE(vco1_mhz);
   1106     EFUN_PRINTF((    "uC Config VCO Rate   = %d (~%d.%03dGHz), %d (~%d.%03dGHz)\n", core_cfg.field.vco_rate
   1107                                                                                   , (vco_mhz / 1000)
   1108                                                                                   , (vco_mhz % 1000)
   1109                                                                                   , pll1_cfg.field.vco_rate
   1110                                                                                   , (vco1_mhz / 1000)
   1111                                                                                   , (vco1_mhz % 1000)               ));
   1112     EFUN_PRINTF((    "Core Config from PCS = %d, %d\n\n"                          , core_cfg.field.core_cfg_from_pcs
   1113                                                                                   , pll1_cfg.field.core_cfg_from_pcs));
   1114         }
   1115     }
   1116     ESTM_PRINTF((    "Tx Lane Addr 0       = %d\n"                                , rdc_tx_lane_addr_0()));
   1117     ESTM_PRINTF((    "Rx Lane Addr 0       = %d\n"                                , rdc_rx_lane_addr_0()));
   1118     ESTM_PRINTF((    "Tx Lane Addr 1       = %d\n"                                , rdc_tx_lane_addr_1()));
   1119     ESTM_PRINTF((    "Rx Lane Addr 1       = %d\n"                                , rdc_rx_lane_addr_1()));
   1120     ESTM_PRINTF((    "Tx Lane Addr 2       = %d\n"                                , rdc_tx_lane_addr_2()));
   1121     ESTM_PRINTF((    "Rx Lane Addr 2       = %d\n"                                , rdc_rx_lane_addr_2()));
   1122     ESTM_PRINTF((    "Tx Lane Addr 3       = %d\n"                                , rdc_tx_lane_addr_3()));
   1123     ESTM_PRINTF((    "Rx Lane Addr 3       = %d\n"                                , rdc_rx_lane_addr_3()));
   1124 #ifdef rdc_tx_lane_addr_4
   1125     ESTM_PRINTF((    "Tx Lane Addr 4       = %d\n"                                , rdc_tx_lane_addr_4()));
   1126     ESTM_PRINTF((    "Rx Lane Addr 4       = %d\n"                                , rdc_rx_lane_addr_4()));
   1127 #endif
   1128 #ifdef rdc_tx_lane_addr_5
   1129     ESTM_PRINTF((    "Tx Lane Addr 5       = %d\n"                                , rdc_tx_lane_addr_5()));
   1130     ESTM_PRINTF((    "Rx Lane Addr 5       = %d\n"                                , rdc_rx_lane_addr_5()));
   1131 #endif
   1132 #ifdef rdc_tx_lane_addr_6
   1133     ESTM_PRINTF((    "Tx Lane Addr 6       = %d\n"                                , rdc_tx_lane_addr_6()));
   1134     ESTM_PRINTF((    "Rx Lane Addr 6       = %d\n"                                , rdc_rx_lane_addr_6()));
   1135 #endif
   1136 #ifdef rdc_tx_lane_addr_7
   1137     ESTM_PRINTF((    "Tx Lane Addr 7       = %d\n"                                , rdc_tx_lane_addr_7()));
   1138     ESTM_PRINTF((    "Rx Lane Addr 7       = %d\n"                                , rdc_rx_lane_addr_7()));
   1139 #endif
   1140     return(ERR_CODE_NONE);
   1141 }
   1142 
   1143 
   1144 err_code_t blackhawk_tsc_display_lane_config(srds_access_t *sa__) {
   1145     struct blackhawk_tsc_uc_lane_config_st lane_cfg;
   1146 
   1147     ENULL_MEMSET(&lane_cfg, 0, sizeof(lane_cfg));
   1148 
   1149     EFUN_PRINTF(("\n\n*************************************\n"                                          ));
   1150     ESTM_PRINTF((   "**** SERDES LANE %d CONFIGURATION ****\n"  , blackhawk_tsc_get_lane(sa__)                 ));
   1151     EFUN_PRINTF((    "*************************************\n\n"                                        ));
   1152     EFUN(                                                         blackhawk_tsc_get_uc_lane_cfg(sa__, &lane_cfg));
   1153     EFUN_PRINTF((    "Lane Config from PCS        = %d\n\n"     , lane_cfg.field.lane_cfg_from_pcs      ));
   1154     EFUN_PRINTF((    "Auto-Neg Enabled            = %d\n"       , lane_cfg.field.an_enabled             ));
   1155     EFUN_PRINTF((    "DFE on                      = %d\n"       , lane_cfg.field.dfe_on                 ));
   1156     
   1157     EFUN_PRINTF((    "DFE low power mode          = %d\n"       , lane_cfg.field.dfe_lp_mode            ));
   1158     EFUN_PRINTF((    "Brdfe_on                    = %d\n"       , lane_cfg.field.force_brdfe_on         ));
   1159     EFUN_PRINTF((    "Media Type                  = %d\n"       , lane_cfg.field.media_type             ));
   1160     EFUN_PRINTF((    "Unreliable LOS              = %d\n"       , lane_cfg.field.unreliable_los         ));
   1161     EFUN_PRINTF((    "Scrambling Disable          = %d\n"       , lane_cfg.field.scrambling_dis         ));
   1162     ESTM_PRINTF((    "Link Training Enable        = %d\n"       , rd_linktrn_ieee_training_enable()     ));
   1163     EFUN_PRINTF((    "CL72 Auto Polarity   Enable = %d\n"       , lane_cfg.field.cl72_auto_polarity_en  ));
   1164     EFUN_PRINTF((    "CL72 Restart timeout Enable = %d\n"       , lane_cfg.field.cl72_restart_timeout_en));
   1165 
   1166     EFUN_PRINTF((    "Force ES Mode               = %d\n"       , lane_cfg.field.force_es               ));
   1167     EFUN_PRINTF((    "Force NS Mode               = %d\n"       , lane_cfg.field.force_ns               ));
   1168     EFUN_PRINTF((    "Link Partner has Precoder En= %d\n"       , lane_cfg.field.lp_has_prec_en         ));
   1169     EFUN_PRINTF((    "Force PAM4 mode             = %d\n"       , lane_cfg.field.force_pam4_mode        ));
   1170     EFUN_PRINTF((    "Force NRZ mode              = %d\n"       , lane_cfg.field.force_nrz_mode         ));
   1171 
   1172     ESTM_PRINTF((    "RX PLL Select               = %d\n"       , rd_rx_pll_select()                    ));
   1173     ESTM_PRINTF((    "TX PLL Select               = %d\n"       , rd_tx_pll_select()                    ));
   1174     ESTM_PRINTF((    "TX OSR Mode Force           = %d\n"       , rd_tx_osr_mode_frc()                  ));
   1175     ESTM_PRINTF((    "TX OSR Mode Force Val       = %d\n"       , rd_tx_osr_mode_frc_val()              ));
   1176     ESTM_PRINTF((    "RX OSR Mode Force           = %d\n"       , rd_rx_osr_mode_frc()                  ));
   1177     ESTM_PRINTF((    "RX OSR Mode Force Val       = %d\n"       , rd_rx_osr_mode_frc_val()              ));
   1178     ESTM_PRINTF((    "TX Polarity Invert          = %d\n"       , rd_tx_pmd_dp_invert()                 ));
   1179     ESTM_PRINTF((    "RX Polarity Invert          = %d\n\n"     , rd_rx_pmd_dp_invert()                 ));
   1180     ESTM_PRINTF((    "TXFIR Range                 = %s\n"       , rd_txfir_nrz_tap_range_sel() ? "NRZ" : "PAM4"));
   1181     ESTM_PRINTF((    "TXFIR Tap0                  = %d\n"       , rd_txfir_tap0_coeff()                 ));
   1182     ESTM_PRINTF((    "TXFIR Tap1                  = %d\n"       , rd_txfir_tap1_coeff()                 ));
   1183     ESTM_PRINTF((    "TXFIR Tap2                  = %d\n"       , rd_txfir_tap2_coeff()                 ));
   1184     ESTM_PRINTF((    "TXFIR Tap3                  = %d\n"       , rd_txfir_tap3_coeff()                 ));
   1185     ESTM_PRINTF((    "TXFIR Tap4                  = %d\n"       , rd_txfir_tap4_coeff()                 ));
   1186     ESTM_PRINTF((    "TXFIR Tap5                  = %d\n"       , rd_txfir_tap5_coeff()                 ));
   1187     ESTM_PRINTF((    "TXFIR Tap6                  = %d\n"       , rd_txfir_tap6_coeff()                 ));
   1188     ESTM_PRINTF((    "TXFIR Tap7                  = %d\n"       , rd_txfir_tap7_coeff()                 ));
   1189     ESTM_PRINTF((    "TXFIR Tap8                  = %d\n"       , rd_txfir_tap8_coeff()                 ));
   1190     ESTM_PRINTF((    "TXFIR Tap9                  = %d\n"       , rd_txfir_tap9_coeff()                 ));
   1191     ESTM_PRINTF((    "TXFIR Tap10                 = %d\n"       , rd_txfir_tap10_coeff()                ));
   1192     ESTM_PRINTF((    "TXFIR Tap11                 = %d\n"       , rd_txfir_tap11_coeff()                ));
   1193     return(ERR_CODE_NONE);
   1194 }
   1195 
   1196 
   1197 err_code_t blackhawk_tsc_display_core_state(srds_access_t *sa__) {
   1198     EFUN(blackhawk_tsc_display_core_state_hdr());
   1199     EFUN(blackhawk_tsc_display_core_state_line(sa__));
   1200     EFUN(blackhawk_tsc_display_core_state_legend());
   1201     return ERR_CODE_NONE;
   1202 }
   1203 
   1204 
   1205 err_code_t blackhawk_tsc_display_lane_debug_status(srds_access_t *sa__) {
   1206     /* startup */
   1207     struct blackhawk_tsc_usr_ctrl_disable_functions_st     ds;
   1208     struct blackhawk_tsc_usr_ctrl_disable_dfe_functions_st dsd;
   1209     /* steady state */
   1210     struct blackhawk_tsc_usr_ctrl_disable_functions_st     dss;
   1211     struct blackhawk_tsc_usr_ctrl_disable_dfe_functions_st dssd;
   1212 
   1213     ENULL_MEMSET(&ds  , 0, sizeof(ds  ));
   1214     ENULL_MEMSET(&dsd , 0, sizeof(dsd ));
   1215     ENULL_MEMSET(&dss , 0, sizeof(dss ));
   1216     ENULL_MEMSET(&dssd, 0, sizeof(dssd));
   1217 
   1218     EFUN_PRINTF(("\n\n************************************\n"                                                     ));
   1219     ESTM_PRINTF((   "**** SERDES LANE %d DEBUG STATUS ****\n"               , blackhawk_tsc_get_lane(sa__)               ));
   1220     EFUN_PRINTF((    "************************************\n\n"                                                   ));
   1221     ESTM_PRINTF((    "Restart Count                                = %d\n"  , rdv_usr_sts_restart_counter()       ));
   1222     ESTM_PRINTF((    "Reset Count                                  = %d\n"  , rdv_usr_sts_reset_counter()         ));
   1223     ESTM_PRINTF((    "PMD Lock Count                               = %d\n\n", rdv_usr_sts_pmd_lock_counter()      ));
   1224     EFUN(blackhawk_tsc_get_usr_ctrl_disable_startup(sa__, &ds));
   1225     
   1226     EFUN_PRINTF((    "Disable Startup PF Adaptation                = %d\n"  , ds.field.pf_adaptation              ));
   1227     EFUN_PRINTF((    "Disable Startup PF2 Adaptation               = %d\n"  , ds.field.pf2_adaptation             ));
   1228     EFUN_PRINTF((    "Disable Startup PF3 Adaptation               = %d\n"  , ds.field.pf3_adaptation             ));
   1229     EFUN_PRINTF((    "Disable Startup DC Adaptation                = %d\n"  , ds.field.dc_adaptation              ));
   1230     EFUN_PRINTF((    "Disable Startup VGA Adaptation               = %d\n"  , ds.field.vga_adaptation             ));
   1231     EFUN_PRINTF((    "Disable Startup Slicer vOffset Tuning        = %d\n"  , ds.field.slicer_voffset_tuning      ));
   1232     EFUN_PRINTF((    "Disable Startup Slicer hOffset Tuning        = %d\n"  , ds.field.slicer_hoffset_tuning      ));
   1233     EFUN_PRINTF((    "Disable Startup Phase offset Adaptation      = %d\n"  , ds.field.phase_offset_adaptation    ));
   1234     EFUN_PRINTF((    "Disable Startup Eye Adaptation               = %d\n"  , ds.field.eye_adaptation             ));
   1235     EFUN_PRINTF((    "Disable Startup All Adaptation               = %d\n\n", ds.field.all_adaptation             ));
   1236     EFUN(                                                            blackhawk_tsc_get_usr_ctrl_disable_startup_dfe(sa__, &dsd));
   1237     
   1238     EFUN_PRINTF((    "Disable Startup DFE Tap1 Adaptation          = %d\n"  , dsd.field.dfe_tap1_adaptation       ));
   1239     EFUN_PRINTF((    "Disable Startup DFE FX Taps Adaptation       = %d\n"  , dsd.field.dfe_fx_taps_adaptation    ));
   1240     EFUN_PRINTF((    "Disable Startup DFE FL Taps Adaptation       = %d\n"  , dsd.field.dfe_fl_taps_adaptation    ));
   1241     EFUN_PRINTF((    "Disable Startup DFE Tap DCD                  = %d\n"  , dsd.field.dfe_dcd_adaptation        ));
   1242     EFUN(                                                           blackhawk_tsc_get_usr_ctrl_disable_steady_state(sa__, &dss));
   1243     
   1244     EFUN_PRINTF((    "Disable Steady State PF Adaptation           = %d\n"  , dss.field.pf_adaptation             ));
   1245     EFUN_PRINTF((    "Disable Steady State PF2 Adaptation          = %d\n"  , dss.field.pf2_adaptation            ));
   1246     EFUN_PRINTF((    "Disable Steady State PF3 Adaptation          = %d\n"  , dss.field.pf3_adaptation            ));
   1247     EFUN_PRINTF((    "Disable Steady State DC Adaptation           = %d\n"  , dss.field.dc_adaptation             ));
   1248     EFUN_PRINTF((    "Disable Steady State VGA Adaptation          = %d\n"  , dss.field.vga_adaptation            ));
   1249     EFUN_PRINTF((    "Disable Steady State Slicer vOffset Tuning   = %d\n"  , dss.field.slicer_voffset_tuning     ));
   1250     EFUN_PRINTF((    "Disable Steady State Slicer hOffset Tuning   = %d\n"  , dss.field.slicer_hoffset_tuning     ));
   1251     EFUN_PRINTF((    "Disable Steady State Phase offset Adaptation = %d\n"  , dss.field.phase_offset_adaptation   ));
   1252     EFUN_PRINTF((    "Disable Steady State Eye Adaptation          = %d\n"  , dss.field.eye_adaptation            ));
   1253     EFUN_PRINTF((    "Disable Steady State All Adaptation          = %d\n\n", dss.field.all_adaptation            ));
   1254     EFUN(                                                      blackhawk_tsc_get_usr_ctrl_disable_steady_state_dfe(sa__, &dssd));
   1255     
   1256     EFUN_PRINTF((    "Disable Steady State DFE Tap1 Adaptation     = %d\n"  , dssd.field.dfe_tap1_adaptation      ));
   1257     EFUN_PRINTF((    "Disable Steady State DFE FX Taps Adaptation  = %d\n"  , dssd.field.dfe_fx_taps_adaptation   ));
   1258     EFUN_PRINTF((    "Disable Steady State DFE FL Taps Adaptation  = %d\n"  , dssd.field.dfe_fl_taps_adaptation   ));
   1259     EFUN_PRINTF((    "Disable Steady State DFE Tap DCD             = %d\n"  , dssd.field.dfe_dcd_adaptation       ));
   1260     ESTM_PRINTF((    "Clk90 offset Adjust                          = %d\n"  , rdv_usr_ctrl_clk90_offset_adjust()  ));
   1261     ESTM_PRINTF((    "Clk90 offset Override                        = %d\n"  , rdv_usr_ctrl_clk90_offset_override()));
   1262     ESTM_PRINTF((    "Lane Event Log Level                         = %d\n"  , rdv_usr_ctrl_lane_event_log_level() ));
   1263 
   1264     return(ERR_CODE_NONE);
   1265 }
   1266 
   1267 static err_code_t _display_ber_scan_data(srds_access_t *sa__, uint8_t ber_scan_mode, uint8_t timer_control, uint8_t max_error_control) {
   1268     uint8_t i,prbs_byte,prbs_multi,time_byte,time_multi;
   1269     uint16_t sts,dataword;
   1270     int16_t offset_start;
   1271     uint8_t cnt;
   1272     uint32_t errors,timer_values;
   1273     int rate,direction;
   1274     uint8_t range250;
   1275     blackhawk_tsc_osr_mode_st osr_mode;
   1276     struct blackhawk_tsc_uc_core_config_st core_config;
   1277 
   1278     ENULL_MEMSET(&core_config,0,sizeof(core_config));
   1279     ENULL_MEMSET(&osr_mode,0,sizeof(osr_mode));
   1280 
   1281     EFUN(blackhawk_tsc_get_uc_core_config(sa__, &core_config));
   1282     EFUN(blackhawk_tsc_INTERNAL_get_osr_mode(sa__, &osr_mode));
   1283 
   1284 #ifdef wr_ams_rx_rxclk_div2p5
   1285     if((osr_mode.rx > BLACKHAWK_TSC_OSX4) && (osr_mode.rx != BLACKHAWK_TSC_OSX2P5)) {
   1286 #else
   1287     if(osr_mode.rx > BLACKHAWK_TSC_OSX4) {
   1288 #endif
   1289         EFUN_PRINTF(("ERROR DIAG display_ber_data: osr mode too high\n"));
   1290         return(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1291     }
   1292     if (osr_mode.rx > BLACKHAWK_TSC_OSX4) { /* BER supported for only BLACKHAWK_TSC_OSX2P5 mode when osr_mode > osx4 */
   1293         rate = (int)(core_config.vco_rate_in_Mhz/2.5);
   1294     }
   1295     else {
   1296         rate = core_config.vco_rate_in_Mhz/(1<<osr_mode.rx);
   1297     }
   1298     direction = (ber_scan_mode & DIAG_BER_NEG) ? -1 : 1 ;
   1299     range250 = (ber_scan_mode & DIAG_BER_P1_NARROW) ? 0 : 1;
   1300 
   1301     EFUN_PRINTF(("\n****  SERDES BER DATA    ****\n"));
   1302     EFUN_PRINTF(("BER MODE = %x %d %d\n",ber_scan_mode,timer_control,max_error_control));
   1303     EFUN_PRINTF(("DATA RATE = %d Mhz\n",rate));
   1304     /* start UC acquisition */
   1305     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("start begin\n"));
   1306     EFUN(blackhawk_tsc_start_ber_scan_test(sa__, ber_scan_mode, timer_control, max_error_control));
   1307     ESTM(offset_start = rd_uc_dsc_data());
   1308     if(ber_scan_mode & DIAG_BER_HORZ) {
   1309         EFUN_PRINTF(("STARTING OFFSET = %d : %d mUI\n",offset_start,(offset_start*1000)>>6));
   1310     } else {
   1311         EFUN_PRINTF(("STARTING OFFSET = %d : %d mV\n",offset_start,blackhawk_tsc_INTERNAL_ladder_setting_to_mV(sa__, (int8_t)offset_start, range250)));
   1312     }
   1313     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("start done\n"));
   1314 
   1315 
   1316     /* This wait is VERY LONG and should be replaced with interupt or something */
   1317     if(DIAG_VERBOSE > 5) {
   1318         do {
   1319             EFUN(USR_DELAY_US(2000000));
   1320             ESTM(sts = rdv_usr_diag_status());
   1321             EFUN_PRINTF(("sts=%04x\n",sts));
   1322 
   1323         } while ((sts & 0x8000) == 0);
   1324     } else {
   1325         EFUN_PRINTF(("Waiting for measurement time approx %d seconds",timer_control+(timer_control>>1)));
   1326         EFUN(blackhawk_tsc_INTERNAL_poll_diag_done(sa__, &sts,timer_control*2000));
   1327     }
   1328     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("delay done\n"));
   1329 
   1330     /* Check for completion read ln.diag_status byte?*/
   1331     ESTM(sts = rdv_usr_diag_status());
   1332     if((sts & 0x8000) == 0) {
   1333         return(blackhawk_tsc_error(sa__, ERR_CODE_DATA_NOTAVAIL));
   1334     }
   1335     cnt = (sts & 0x00FF)/3;
   1336     for(i=0;i < cnt;i++) {
   1337         /* Read 2 bytes of data */
   1338         EFUN(blackhawk_tsc_pmd_uc_cmd(sa__, CMD_READ_DIAG_DATA_WORD, 0, 200));
   1339         ESTM(dataword = rd_uc_dsc_data());           /* LSB contains 2 -4bit nibbles */
   1340         time_byte = (uint8_t)(dataword>>8);          /* MSB is time byte */
   1341         prbs_multi = (uint8_t)dataword & 0x0F;       /* split nibbles */
   1342         time_multi = (uint8_t)dataword>>4;
   1343         /* Read 1 bytes of data */
   1344         EFUN(blackhawk_tsc_pmd_uc_cmd(sa__, CMD_READ_DIAG_DATA_BYTE, 0, 200));
   1345         ESTM(prbs_byte = (uint8_t)rd_uc_dsc_data());
   1346         errors = blackhawk_tsc_INTERNAL_float12_to_uint32(prbs_byte,prbs_multi); /* convert 12bits to uint32 */
   1347         timer_values = (blackhawk_tsc_INTERNAL_float12_to_uint32(time_byte,time_multi)<<3);
   1348         if(DIAG_VERBOSE < 5) {
   1349             if (!(i % 4))  {
   1350                 EFUN_PRINTF(("\n"));
   1351             }
   1352             if(ber_scan_mode & DIAG_BER_HORZ) {
   1353                 EFUN_PRINTF(("%d %d %d ",direction*(((SRDS_ABS(offset_start)-i)*1000)>>6),errors,timer_values));
   1354             } else {
   1355                 EFUN_PRINTF(("%d %d %d ",direction*blackhawk_tsc_INTERNAL_ladder_setting_to_mV(sa__, (int8_t)SRDS_ABS(offset_start)-i, range250),errors,timer_values));
   1356             }
   1357 
   1358         } else {
   1359             EFUN_PRINTF(("BER Errors=%d (%02x<<%d): Time=%d (%02x<<%d)\n",errors,prbs_byte,prbs_multi,timer_values,time_byte,time_multi<<3));
   1360         }
   1361         /*if(timer_values == 0 && errors == 0) break;*/
   1362     }
   1363     EFUN_PRINTF(("\n"));
   1364     EFUN(blackhawk_tsc_pmd_uc_cmd(sa__, CMD_CAPTURE_BER_END,0x00,2000));
   1365 
   1366   return(ERR_CODE_NONE);
   1367 }
   1368 
   1369 /*******************************************/
   1370 /*  Diagnostic Functions Required for SDK  */
   1371 /*******************************************/
   1372 
   1373 /* Required Diagnostic Functions */
   1374 err_code_t blackhawk_tsc_display_diag_data(srds_access_t *sa__, uint16_t  diag_level) {
   1375     uint8_t rx_lock, micro_stop, core, lane;
   1376     uint32_t api_version;
   1377     EFUN_PRINTF(("\n**** SERDES DISPLAY DIAG DATA ****\n"));
   1378     ESTM_PRINTF(("Rev ID Letter  = %02X\n", rdc_revid_rev_letter()));
   1379     ESTM_PRINTF(("Rev ID Process = %02X\n", rdc_revid_process()));
   1380     ESTM_PRINTF(("Rev ID Model   = %02X\n", rdc_revid_model()));
   1381     ESTM_PRINTF(("Rev ID Model   = %02X\n", rdc_revid2()));
   1382     ESTM_PRINTF(("Rev ID # Lanes = %d\n"  ,rdc_revid_multiplicity()));
   1383     ESTM_PRINTF(("Core = %d; LANE = %d\n",blackhawk_tsc_get_core(sa__),blackhawk_tsc_get_lane(sa__)));
   1384     EFUN(blackhawk_tsc_version(sa__, &api_version));
   1385     EFUN_PRINTF(("SERDES API Version         = %06X\n",api_version));
   1386     ESTM_PRINTF(("Common Ucode Version       = %04X", rdcv_common_ucode_version()));
   1387     ESTM_PRINTF(("_%02X\n", rdcv_common_ucode_minor_version()));
   1388     ESTM_PRINTF(("AFE Hardware Version       = 0x%X\n\n", rdcv_afe_hardware_version()));
   1389 
   1390     /* stop micro so all accesses are consistent */
   1391     ESTM(rx_lock = rd_pmd_rx_lock());
   1392     {
   1393         err_code_t err_code=ERR_CODE_NONE;
   1394         micro_stop = blackhawk_tsc_INTERNAL_stop_micro(sa__,rx_lock,&err_code);
   1395         if(err_code) USR_PRINTF(("Unable to stop microcontroller,  following data is suspect\n"));
   1396     }
   1397 
   1398     EFUN(blackhawk_tsc_display_lane_state_hdr());
   1399     EFUN(blackhawk_tsc_display_lane_state(sa__));
   1400 
   1401     if(diag_level & SRDS_DIAG_LANE) {
   1402         struct blackhawk_tsc_detailed_lane_status_st lane_st;
   1403 
   1404         ENULL_MEMSET(&lane_st, 0, sizeof(lane_st));
   1405         EFUN(blackhawk_tsc_log_full_pmd_state(sa__, &lane_st));
   1406 
   1407         EFUN(blackhawk_tsc_disp_full_pmd_state(sa__, &lane_st, 1));
   1408     }
   1409 
   1410     if(diag_level & SRDS_DIAG_CORE) {
   1411         EFUN(blackhawk_tsc_display_core_state_hdr());
   1412         EFUN(blackhawk_tsc_display_core_state_line(sa__));
   1413     }
   1414     if(diag_level & SRDS_DIAG_TIMESTAMP) {
   1415         EFUN(blackhawk_tsc_test_uc_timestamp(sa__));
   1416     }
   1417     if(diag_level & SRDS_DIAG_EVENT_SAFE) {
   1418         blackhawk_tsc_INTERNAL_event_log_dump_state_t state;
   1419         uint8_t micro_num = 0;
   1420         srds_info_t *blackhawk_tsc_info_ptr;
   1421         blackhawk_tsc_info_ptr = blackhawk_tsc_INTERNAL_get_blackhawk_tsc_info_ptr_with_check(sa__);
   1422 #ifdef PHYMOD_SUPPORT
   1423         if ( blackhawk_tsc_info_ptr == NULL ) {
   1424             blackhawk_tsc_init_blackhawk_tsc_info(sa__);
   1425         } else if (blackhawk_tsc_info_ptr->signature != SRDS_INFO_SIGNATURE) {
   1426             blackhawk_tsc_init_blackhawk_tsc_info(sa__);
   1427         }
   1428 #endif /* PHYMOD_SUPPORT */
   1429         for (; micro_num<blackhawk_tsc_info_ptr->micro_count; ++micro_num)
   1430         {
   1431             state.index = 0;
   1432             state.line_start_index = 0;
   1433             EFUN(blackhawk_tsc_INTERNAL_read_event_log_with_callback(sa__, micro_num, 1, &state, blackhawk_tsc_INTERNAL_event_log_dump_callback));
   1434             EFUN(blackhawk_tsc_INTERNAL_event_log_dump_callback(&state, 0, 0));
   1435         }
   1436     }
   1437     if(diag_level & SRDS_DIAG_EVENT) {
   1438         EFUN(blackhawk_tsc_read_event_log(sa__));
   1439     }
   1440     if(diag_level & SRDS_DIAG_EYE) {
   1441         EFUN(blackhawk_tsc_display_eye_scan(sa__));
   1442     }
   1443     /* currently REG_CORE and REG_LANE dump same data. */
   1444     core = blackhawk_tsc_get_core(sa__);
   1445     lane = blackhawk_tsc_get_lane(sa__);
   1446 
   1447     if((diag_level & SRDS_DIAG_REG_CORE)
   1448        || (diag_level & SRDS_DIAG_REG_LANE)) {
   1449         EFUN(blackhawk_tsc_reg_dump(sa__, core, lane, NULL));
   1450     }
   1451     if(diag_level & SRDS_DIAG_UC_CORE) {
   1452         EFUN(blackhawk_tsc_uc_core_var_dump(sa__, core, NULL));
   1453 
   1454         {
   1455 	    uint8_t orig_lane, num_micros, lane;
   1456 
   1457 	    ESTM(num_micros = rdc_micro_num_uc_cores());
   1458 	    orig_lane = blackhawk_tsc_get_physical_lane(sa__);
   1459 	    for (lane = 0; lane < num_micros*2; lane += 2) {
   1460 		    EFUN(blackhawk_tsc_set_physical_lane(sa__, lane));
   1461 
   1462 		    EFUN(blackhawk_tsc_uc_micro_var_dump(sa__, core, lane, NULL));
   1463 	    }
   1464 	    EFUN(blackhawk_tsc_set_physical_lane(sa__, orig_lane));
   1465         }
   1466     }
   1467     if(diag_level & SRDS_DIAG_UC_LANE) {
   1468 
   1469         EFUN(blackhawk_tsc_uc_lane_var_dump(sa__, core, lane, NULL));
   1470     }
   1471     if(diag_level & SRDS_DIAG_LANE_DEBUG) {
   1472         EFUN(blackhawk_tsc_display_lane_debug_status(sa__));
   1473     }
   1474     if(diag_level & SRDS_DIAG_BER_VERT) {
   1475         /* display ber projections for all channels */
   1476         uint8_t ber_mode = DIAG_BER_VERT | DIAG_BER_POS;
   1477         uint8_t timer_control = 23;       /* 30 seconds */
   1478         uint8_t err_threshold = 100 / 16; /* 100 errors */
   1479         EFUN(_display_ber_scan_data(sa__, ber_mode, timer_control,  err_threshold));
   1480         ber_mode = DIAG_BER_VERT | DIAG_BER_NEG;
   1481         EFUN(_display_ber_scan_data(sa__, ber_mode, timer_control,  err_threshold));
   1482     }
   1483     if(diag_level & SRDS_DIAG_BER_HORZ) {
   1484         /* display ber projections for all channels */
   1485         uint8_t ber_mode = DIAG_BER_HORZ | DIAG_BER_POS;
   1486         uint8_t timer_control = 23;       /* 30 seconds */
   1487         uint8_t err_threshold = 100 / 16; /* 100 errors */
   1488         EFUN(_display_ber_scan_data(sa__, ber_mode, timer_control,  err_threshold));
   1489         ber_mode = DIAG_BER_HORZ | DIAG_BER_NEG;
   1490         EFUN(_display_ber_scan_data(sa__, ber_mode, timer_control,  err_threshold));
   1491     }
   1492 
   1493     /* re enable micro */
   1494     if (!micro_stop) {
   1495         EFUN(blackhawk_tsc_stop_rx_adaptation(sa__, 0));
   1496     }
   1497 
   1498     EFUN_PRINTF(("\n\n"));
   1499     return (ERR_CODE_NONE);
   1500 
   1501 }
   1502 
   1503 typedef struct {
   1504     uint16_t addr;
   1505     uint8_t  line_byte_counter;
   1506 } blackhawk_tsc_diag_access_callback_state_t;
   1507 
   1508 static err_code_t blackhawk_tsc_diag_access_read_byte_callback(void *arg, uint8_t byte_count, uint16_t data) {
   1509     blackhawk_tsc_diag_access_callback_state_t * const state_ptr = (blackhawk_tsc_diag_access_callback_state_t *)arg;
   1510     while (byte_count > 0) {
   1511         if (state_ptr->line_byte_counter == 0) {
   1512             USR_PRINTF(("\n%04x  ", state_ptr->addr));
   1513         }
   1514         USR_PRINTF(("%02x ", data & 0xFF));
   1515         ++state_ptr->addr;
   1516         state_ptr->line_byte_counter = (state_ptr->line_byte_counter+1) % 16;
   1517         data >>= 8;
   1518         --byte_count;
   1519     }
   1520     return (ERR_CODE_NONE);
   1521 }
   1522 
   1523 static err_code_t blackhawk_tsc_diag_access_read_word_callback(void *arg, uint8_t byte_count, uint16_t data) {
   1524     blackhawk_tsc_diag_access_callback_state_t * const state_ptr = (blackhawk_tsc_diag_access_callback_state_t *)arg;
   1525     UNUSED(byte_count);
   1526 
   1527     if (state_ptr->line_byte_counter == 0) {
   1528         USR_PRINTF(("\n%04x  ", state_ptr->addr));
   1529     }
   1530     USR_PRINTF(("%04x ", data));
   1531     state_ptr->addr += 2;
   1532     state_ptr->line_byte_counter = (state_ptr->line_byte_counter+2) % 16;
   1533     return (ERR_CODE_NONE);
   1534 }
   1535 
   1536 /* Required Diagnostic Functions */
   1537 err_code_t blackhawk_tsc_diag_access(srds_access_t *sa__, enum srds_diag_access_enum type, uint16_t addr, uint16_t data, uint16_t param) {
   1538     srds_info_t *blackhawk_tsc_info_ptr = blackhawk_tsc_INTERNAL_get_blackhawk_tsc_info_ptr_with_check(sa__);
   1539     blackhawk_tsc_diag_access_callback_state_t state;
   1540 
   1541 #ifdef PHYMOD_SUPPORT
   1542     if ( blackhawk_tsc_info_ptr == NULL ) {
   1543         blackhawk_tsc_init_blackhawk_tsc_info(sa__);
   1544     } else if (blackhawk_tsc_info_ptr->signature != SRDS_INFO_SIGNATURE) {
   1545         blackhawk_tsc_init_blackhawk_tsc_info(sa__);
   1546     }
   1547 #endif /* PHYMOD_SUPPORT */
   1548     EFUN(blackhawk_tsc_INTERNAL_verify_blackhawk_tsc_info(blackhawk_tsc_info_ptr, sa__));
   1549     state.addr = addr;
   1550     state.line_byte_counter = 0;
   1551 
   1552 
   1553     switch(type) {
   1554     case SRDS_REG_READ:      {
   1555                              uint16_t tmp = 0;
   1556                              if(data > 1) {
   1557                                  uint16_t i;
   1558                                  EFUN_PRINTF(("\n****  SERDES BLK REGISTER READ    ****"));
   1559                                  for (i = 0; i < data; i++) {
   1560                                      if (!(i % 16))  {
   1561                                          ESTM_PRINTF(("\n%04x ",i+addr));
   1562                                      }
   1563                                      EFUN(blackhawk_tsc_pmd_rdt_reg(sa__, i+addr,&tmp));
   1564                                      ESTM_PRINTF(("%04x ", tmp));
   1565                                  }
   1566                                  EFUN_PRINTF(("\n"));
   1567                              } else {
   1568                                  EFUN(blackhawk_tsc_pmd_rdt_reg(sa__, addr,&tmp));
   1569                                  EFUN_PRINTF(("Register Read: x%04x = x%04x\n",addr,tmp));
   1570                              }
   1571                              } break;
   1572     case SRDS_REG_RMW:       {
   1573                              uint16_t tmp = 0, tmp2;
   1574                              EFUN(blackhawk_tsc_pmd_rdt_reg(sa__, addr,&tmp));
   1575                              tmp2 = (tmp & ~param) | (param & data);
   1576                              EFUN(blackhawk_tsc_pmd_wr_reg(sa__, addr,tmp2));
   1577                              EFUN_PRINTF(("Register RMW: x%04x = x%04x -> x%04x\n",addr,tmp,tmp2));
   1578                              } break;
   1579     case SRDS_CORE_RAM_READ_BYTE: {
   1580                              if(data > 1) {
   1581                                  EFUN_PRINTF(("\n****  SERDES BLK CORE RAM READ BYTE   ****"));
   1582                                  EFUN(blackhawk_tsc_INTERNAL_rdblk_uc_generic_ram(sa__,
   1583                                                                            addr + blackhawk_tsc_info_ptr->core_var_ram_base,
   1584                                                                            data,
   1585                                                                            0,
   1586                                                                            data,
   1587                                                                            &state,
   1588                                                                            blackhawk_tsc_diag_access_read_byte_callback));
   1589                                  EFUN_PRINTF(("\n"));
   1590                              } else {
   1591                                  ESTM_PRINTF(("Core RAM Read byte: x%04x = x%02x\n",(uint8_t)addr,blackhawk_tsc_rdbc_uc_var(sa__, __ERR, (uint8_t)addr)));
   1592                              }
   1593                              } break;
   1594     case SRDS_LANE_RAM_READ_BYTE: {
   1595                              if(data > 1) {
   1596                                  EFUN_PRINTF(("\n****  SERDES BLK LANE RAM READ BYTE   ****"));
   1597                                  EFUN(blackhawk_tsc_INTERNAL_rdblk_uc_generic_ram(sa__, (addr + blackhawk_tsc_info_ptr->lane_var_ram_base + (blackhawk_tsc_get_physical_lane(sa__) * blackhawk_tsc_info_ptr->lane_var_ram_size)),
   1598                                                                            data,
   1599                                                                            0,
   1600                                                                            data,
   1601                                                                            &state,
   1602                                                                            blackhawk_tsc_diag_access_read_byte_callback));
   1603                                  EFUN_PRINTF(("\n"));
   1604                              } else {
   1605                                  ESTM_PRINTF(("Lane RAM Read byte: x%04x = x%02x\n",addr,blackhawk_tsc_rdbl_uc_var(sa__, __ERR,addr)));
   1606                              }
   1607                              } break;
   1608     case SRDS_CORE_RAM_READ_WORD: {
   1609                              if(data > 1) {
   1610                                  EFUN_PRINTF(("\n****  SERDES BLK CORE RAM READ WORD   ****"));
   1611                                  EFUN(blackhawk_tsc_INTERNAL_rdblk_uc_generic_ram(sa__,
   1612                                                                            addr + blackhawk_tsc_info_ptr->core_var_ram_base,
   1613                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1614                                                                            0,
   1615                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1616                                                                            &state,
   1617                                                                            blackhawk_tsc_diag_access_read_word_callback));
   1618                                  EFUN_PRINTF(("\n"));
   1619                              } else {
   1620                                  ESTM_PRINTF(("Core RAM Read word: x%04x = x%04x\n",addr,blackhawk_tsc_rdwc_uc_var(sa__, __ERR, (uint8_t)addr)));
   1621                              }
   1622                              } break;
   1623     case SRDS_LANE_RAM_READ_WORD: {
   1624                              if(data > 1) {
   1625                                  EFUN_PRINTF(("\n****  SERDES BLK LANE RAM READ WORD   ****"));
   1626                                  EFUN(blackhawk_tsc_INTERNAL_rdblk_uc_generic_ram(sa__, (addr + blackhawk_tsc_info_ptr->lane_var_ram_base + (blackhawk_tsc_get_physical_lane(sa__) * blackhawk_tsc_info_ptr->lane_var_ram_size)),
   1627                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1628                                                                            0,
   1629                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1630                                                                            &state,
   1631                                                                            blackhawk_tsc_diag_access_read_word_callback));
   1632                                  EFUN_PRINTF(("\n"));
   1633                              } else {
   1634                                  ESTM_PRINTF(("Lane RAM Read word: x%04x = x%04x\n",addr,blackhawk_tsc_rdwl_uc_var(sa__, __ERR, addr)));
   1635                              }
   1636                              } break;
   1637     case SRDS_CORE_RAM_RMW_BYTE:  {
   1638                              uint8_t tmp, tmp2;
   1639                              ESTM(tmp = blackhawk_tsc_rdbc_uc_var(sa__, __ERR, (uint8_t)addr));
   1640                              tmp2 = (tmp & (uint8_t)~param) | ((uint8_t)param & data);
   1641                              EFUN(blackhawk_tsc_wrbc_uc_var(sa__, (uint8_t)addr,tmp2));
   1642                              EFUN_PRINTF(("Core RAM RMW byte: x%04x = x%02x -> x%02x\n",addr,tmp,tmp2));
   1643                              } break;
   1644     case SRDS_LANE_RAM_RMW_BYTE:  {
   1645                              uint8_t tmp, tmp2;
   1646                              ESTM(tmp = blackhawk_tsc_rdbl_uc_var(sa__, __ERR,addr));
   1647                              tmp2 = (tmp & (uint8_t)~param) | ((uint8_t)param & data);
   1648                              EFUN(blackhawk_tsc_wrbl_uc_var(sa__, addr,tmp2));
   1649                              EFUN_PRINTF(("Lane RAM RMW byte: x%04x = x%02x -> x%02x\n",addr,tmp,tmp2));
   1650                              } break;
   1651     case SRDS_CORE_RAM_RMW_WORD:  {
   1652                              uint16_t tmp, tmp2;
   1653                              ESTM(tmp = blackhawk_tsc_rdwc_uc_var(sa__, __ERR, (uint8_t)addr));
   1654                              tmp2 = (tmp & ~param) | (param & data);
   1655                              EFUN(blackhawk_tsc_wrwc_uc_var(sa__, (uint8_t)addr,tmp2));
   1656                              EFUN_PRINTF(("Core RAM RMW word: x%04x = x%04x -> x%04x\n",addr,tmp,tmp2));
   1657                              } break;
   1658     case SRDS_LANE_RAM_RMW_WORD:  {
   1659                              uint16_t tmp, tmp2;
   1660                              ESTM(tmp = blackhawk_tsc_rdwl_uc_var(sa__, __ERR,addr));
   1661                              tmp2 = (tmp & ~param) | (param & data);
   1662                              EFUN(blackhawk_tsc_wrwl_uc_var(sa__, addr,tmp2));
   1663                              EFUN_PRINTF(("Lane RAM RMW word: x%04x = x%04x -> x%04x\n",addr,tmp,tmp2));
   1664                              } break;
   1665     case SRDS_GLOB_RAM_READ_BYTE: {
   1666                              if(data > 1) {
   1667                                  EFUN_PRINTF(("\n****  SERDES BLK GLOB RAM READ BYTE   ****"));
   1668                                  EFUN(blackhawk_tsc_INTERNAL_rdblk_uc_generic_ram(sa__,
   1669                                                                            0x20000000 | (uint32_t)addr,
   1670                                                                            data,
   1671                                                                            0,
   1672                                                                            data,
   1673                                                                            &state,
   1674                                                                            blackhawk_tsc_diag_access_read_byte_callback));
   1675                                  EFUN_PRINTF(("\n"));
   1676                              } else {
   1677                                  ESTM_PRINTF(("Glob RAM Read byte: x%04x = x%02x\n",addr,blackhawk_tsc_INTERNAL_rdb_uc_var(sa__, __ERR,addr)));
   1678                              }
   1679                              } break;
   1680     case SRDS_GLOB_RAM_RMW_BYTE:  {
   1681                              uint8_t tmp, tmp2;
   1682                              ESTM(tmp = blackhawk_tsc_INTERNAL_rdb_uc_var(sa__, __ERR,addr));
   1683                              tmp2 = (tmp & (uint8_t)~param) | ((uint8_t)param & data);
   1684                              EFUN(blackhawk_tsc_INTERNAL_wrb_uc_var(sa__, addr,tmp2));
   1685                              EFUN_PRINTF(("Glob RAM RMW byte: x%04x = x%02x -> x%02x\n",addr,tmp,tmp2));
   1686                              } break;
   1687     case SRDS_GLOB_RAM_READ_WORD: {
   1688                              if(data > 1) {
   1689                                  EFUN_PRINTF(("\n****  SERDES BLK GLOB RAM READ WORD   ****"));
   1690                                  EFUN(blackhawk_tsc_INTERNAL_rdblk_uc_generic_ram(sa__,
   1691                                                                            0x20000000 | (uint32_t)addr,
   1692                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1693                                                                            0,
   1694                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1695                                                                            &state,
   1696                                                                            blackhawk_tsc_diag_access_read_word_callback));
   1697                                  EFUN_PRINTF(("\n"));
   1698                              } else {
   1699                                  ESTM_PRINTF(("Glob RAM Read word: x%04x = x%04x\n",addr,blackhawk_tsc_INTERNAL_rdw_uc_var(sa__, __ERR,addr)));
   1700                              }
   1701                              } break;
   1702     case SRDS_GLOB_RAM_RMW_WORD:  {
   1703                              uint16_t tmp, tmp2;
   1704                              ESTM(tmp = blackhawk_tsc_INTERNAL_rdw_uc_var(sa__, __ERR,addr));
   1705                              tmp2 = (tmp & ~param) | (param & data);
   1706                              EFUN(blackhawk_tsc_INTERNAL_wrw_uc_var(sa__, addr,tmp2));
   1707                              EFUN_PRINTF(("Glob RAM RMW word: x%04x = x%04x -> x%04x\n",addr,tmp,tmp2));
   1708                              } break;
   1709     case SRDS_UC_CMD:        {
   1710                              uint16_t tmp;
   1711                              EFUN(blackhawk_tsc_pmd_uc_cmd_with_data(sa__, (enum srds_pmd_uc_cmd_enum)addr, (uint8_t)param, data, GRACEFUL_STOP_TIME));
   1712                              ESTM(tmp = rd_uc_dsc_data());
   1713                              EFUN_PRINTF(("uC Command: cmd=x%02x supp=x%02x data=x%04x returned=x%04x\n",addr,param,data,tmp));
   1714                              } break;
   1715     case SRDS_PROG_RAM_READ_BYTE: {
   1716                              if(data > 1) {
   1717                                  EFUN_PRINTF(("\n****  SERDES BLK PROG RAM READ BYTE   ****"));
   1718                                  EFUN(blackhawk_tsc_INTERNAL_rdblk_uc_generic_ram(sa__,
   1719                                                                            addr,
   1720                                                                            data,
   1721                                                                            0,
   1722                                                                            data,
   1723                                                                            &state,
   1724                                                                            blackhawk_tsc_diag_access_read_byte_callback));
   1725                                  EFUN_PRINTF(("\n"));
   1726                              } else {
   1727                                  ESTM_PRINTF(("Prog RAM Read byte: x%04x = x%02x\n",addr,blackhawk_tsc_INTERNAL_rdb_uc_var(sa__, __ERR,addr)));
   1728                              }
   1729                              } break;
   1730     case SRDS_PROG_RAM_READ_WORD: {
   1731                              if(data > 1) {
   1732                                  EFUN_PRINTF(("\n****  SERDES BLK PROG RAM READ WORD   ****"));
   1733                                  EFUN(blackhawk_tsc_INTERNAL_rdblk_uc_generic_ram(sa__,
   1734                                                                            addr,
   1735                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1736                                                                            0,
   1737                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1738                                                                            &state,
   1739                                                                            blackhawk_tsc_diag_access_read_word_callback));
   1740                                  EFUN_PRINTF(("\n"));
   1741                              } else {
   1742                                  ESTM_PRINTF(("Prog RAM Read word: x%04x = x%04x\n",addr,blackhawk_tsc_INTERNAL_rdw_uc_var(sa__, __ERR,addr)));
   1743                              }
   1744                              } break;
   1745     case SRDS_BER_PROJ_DATA: {
   1746                              /* display ber projections for all channels */
   1747                              EFUN(_display_ber_scan_data(sa__, (uint8_t)addr, (uint8_t)data,  (uint8_t)(param>>4)));
   1748                              } break;
   1749     case SRDS_EN_BREAKPOINT: 
   1750     case SRDS_GOTO_BREAKPOINT:
   1751     case SRDS_RD_BREAKPOINT:
   1752     case SRDS_DIS_BREAKPOINT:
   1753     default: EFUN_PRINTF(("Invalid request type blackhawk_tsc_diag_access\n"));
   1754     }
   1755 
   1756     return(ERR_CODE_NONE);
   1757 }
   1758 
   1759 err_code_t blackhawk_tsc_display_state (srds_access_t *sa__) {
   1760     EFUN(blackhawk_tsc_display_core_state(sa__));
   1761     EFUN(blackhawk_tsc_display_lane_state_hdr());
   1762     EFUN(blackhawk_tsc_display_lane_state(sa__));
   1763     EFUN(blackhawk_tsc_display_lane_state_legend());
   1764     return(ERR_CODE_NONE);
   1765 }
   1766 
   1767 err_code_t blackhawk_tsc_display_config (srds_access_t *sa__) {
   1768     EFUN(blackhawk_tsc_display_core_config(sa__));
   1769     EFUN(blackhawk_tsc_display_lane_config(sa__));
   1770     return(ERR_CODE_NONE);
   1771 }
   1772 
   1773 /*************************/
   1774 /*  Temperature forcing  */
   1775 /*************************/
   1776 
   1777 err_code_t blackhawk_tsc_force_die_temperature (srds_access_t *sa__, int16_t die_temp) {
   1778     /* disable force */
   1779     if(die_temp == -255) {
   1780         EFUN(wrc_micro_pvt_tempdata_frc(0));
   1781         return(ERR_CODE_NONE);
   1782     }
   1783 
   1784     /* enable force */
   1785     if (die_temp>130)
   1786         die_temp = 130;
   1787     if (die_temp<-45)
   1788         die_temp = -45;
   1789 
   1790     EFUN(wrc_micro_pvt_tempdata_frcval(_degC_to_bin(die_temp)));
   1791     EFUN(wrc_micro_pvt_tempdata_frc(1));
   1792 
   1793     return(ERR_CODE_NONE);
   1794 }
   1795 
   1796 /**********************/
   1797 /*  CL72/CL93 Status  */
   1798 /**********************/
   1799 
   1800 
   1801 
   1802 err_code_t blackhawk_tsc_display_linktrn_status(srds_access_t *sa__) {
   1803   EFUN_PRINTF(("\n\n***************************\n"                                                                                                                                    ));
   1804   ESTM_PRINTF((   "** LANE %d CL93n72 Status **\n"                                                                                           , blackhawk_tsc_get_lane(sa__)                  ));
   1805   EFUN_PRINTF((    "***************************\n"                                                                                                                                    ));
   1806   ESTM_PRINTF((    "linktrn_signal_detect         = %d   (1 = Link training FSM in SEND_DATA state;     0 = Link in training state)"  "\n", rd_linktrn_training_fsm_signal_detect()));
   1807   ESTM_PRINTF((    "linktrn_ieee_training_failure = %d   (1 = Training failure detected;                0 = Training failure not detected)\n", rd_linktrn_ieee_training_failure()     ));
   1808   ESTM_PRINTF((    "linktrn_ieee_training_status  = %d   (1 = Start-up protocol in progress;            0 = Start-up protocol complete)" "\n", rd_linktrn_ieee_training_status()      ));
   1809   ESTM_PRINTF((    "linktrn_ieee_receiver_status  = %d   (1 = Receiver trained and ready to receive;    0 = Receiver training)"        "\n\n", rd_linktrn_ieee_receiver_status()      ));
   1810   return(ERR_CODE_NONE);
   1811 }
   1812 
   1813 
   1814 
   1815