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

merlin16_diag.c (83618B)


      1 /***********************************************************************************
      2  ***********************************************************************************
      3  *  File Name     :  merlin16_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 merlin16_diag.c
     23  * Implementation of API functions
     24  */
     25 
     26 #ifdef NON_SDK
     27 #include <stdio.h>
     28 #endif
     29 
     30 #ifdef _MSC_VER
     31 /* Enclose all standard headers in a pragma to remove warings for MS compiler */
     32 #pragma warning( push, 0 )
     33 #endif
     34 
     35 #ifdef SERDES_API_FLOATING_POINT
     36 #include <math.h>
     37 #endif
     38 #ifdef _MSC_VER
     39 #pragma warning( pop )
     40 #endif
     41 
     42 #include <phymod/phymod.h>
     43 #include <phymod/phymod_system.h>
     44 #include "merlin16_diag.h"
     45 #include "merlin16_access.h"
     46 #include "merlin16_config.h"
     47 #include "merlin16_debug_functions.h"
     48 #include "merlin16_functions.h"
     49 #include "merlin16_internal.h"
     50 #include "merlin16_internal_error.h"
     51 #include "merlin16_prbs.h"
     52 #include "merlin16_select_defns.h"
     53 
     54 
     55 /************************************/
     56 /*  Display Eye Scan                */
     57 /************************************/
     58 
     59 
     60 /* This is best method for terminal ASCII display */
     61 err_code_t merlin16_display_eye_scan(srds_access_t *sa__) {
     62     uint32_t   stripe[64] = {0};
     63     uint16_t   status = 0;
     64     int8_t     y,y_max,y_step;
     65 
     66     y_max  = EYE_SCAN_NRZ_VERTICAL_IDX_MAX;
     67     y_step = EYE_SCAN_NRZ_VERTICAL_STEP;
     68 
     69     EFUN(merlin16_display_eye_scan_header(1));
     70 
     71     /* start horizontal acquisition */
     72     {   err_code_t err_code = merlin16_meas_eye_scan_start(sa__, EYE_SCAN_HORIZ);
     73         if (err_code) {
     74             EFUN((merlin16_meas_eye_scan_done(sa__), err_code));
     75         }
     76     }
     77 
     78     for (y = y_max;y>=-y_max;y=y-y_step)
     79     {
     80         {   err_code_t err_code = merlin16_read_eye_scan_stripe(sa__, &stripe[0], &status);
     81             if (err_code) {
     82                 EFUN((merlin16_meas_eye_scan_done(sa__), err_code));
     83             }
     84         }
     85         EFUN(merlin16_display_eye_scan_stripe(sa__, y,&stripe[0]));
     86         EFUN_PRINTF(("\n"));
     87     }
     88     /* stop acquisition */
     89     EFUN(merlin16_meas_eye_scan_done(sa__));
     90     EFUN(merlin16_display_eye_scan_footer(1));
     91 
     92     return(ERR_CODE_NONE);
     93 }
     94 
     95 err_code_t merlin16_meas_eye_scan_start(srds_access_t *sa__, uint8_t direction) {
     96     uint8_t lock;
     97     
     98     ESTM(lock = rd_pmd_rx_lock());
     99     if(lock == 0) {
    100           EFUN_PRINTF(("Error: No PMD_RX_LOCK on lane requesting 2D eye scan\n"));
    101           return(ERR_CODE_DIAG_SCAN_NOT_COMPLETE);
    102     }
    103     if(direction == EYE_SCAN_VERTICAL) {
    104         EFUN(merlin16_pmd_uc_diag_cmd(sa__, CMD_UC_DIAG_START_VSCAN_EYE,GRACEFUL_STOP_TIME));
    105     } else if(direction == EYE_SCAN_HORIZ) {
    106         EFUN(merlin16_pmd_uc_diag_cmd(sa__, CMD_UC_DIAG_START_HSCAN_EYE,GRACEFUL_STOP_TIME));
    107     } else if(direction == EYE_SCAN_SLICE) {
    108         EFUN(merlin16_pmd_uc_diag_cmd(sa__, CMD_UC_DIAG_START_EYE_SLICE,GRACEFUL_STOP_TIME));
    109     }
    110     return(ERR_CODE_NONE);
    111 }
    112 
    113 err_code_t merlin16_INTERNAL_poll_diag_data(srds_access_t *sa__, const merlin16_info_t *merlin16_info_ptr, uint16_t *status, uint8_t *diag_rd_ptr, uint8_t byte_count, uint32_t timeout_ms) {
    114     const uint32_t lane_diag_size = merlin16_info_ptr->diag_mem_ram_size;
    115     uint16_t loop;
    116 
    117     *diag_rd_ptr = 0;
    118 
    119     if(!status) {
    120         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    121     }
    122         
    123     /** If the byte_count is too high, then there might be problems not updating
    124      *  the read pointer fast enough.
    125      */
    126     if (byte_count > (lane_diag_size / 2)) {
    127         ESTM_PRINTF(("\nERROR : merlin16_INTERNAL_poll_diag_data() has excessive byte count of %d.\n", byte_count));
    128         return (_error(ERR_CODE_DIAG_TIMEOUT));
    129     }
    130 
    131     ESTM(*diag_rd_ptr = rdv_usr_diag_rd_ptr());
    132 
    133     /* Wait until byte_count bytes are available to be read in the diagnostic memory. */
    134     loop = 0;
    135     while (1) {
    136         uint8_t diag_wr_ptr, full_count;
    137 
    138         ESTM(diag_wr_ptr = rdv_usr_diag_wr_ptr());
    139         if (diag_wr_ptr >= *diag_rd_ptr) {
    140             full_count = diag_wr_ptr - *diag_rd_ptr;
    141         } else {
    142             full_count = (uint16_t)diag_wr_ptr + lane_diag_size - *diag_rd_ptr;
    143         }
    144         if (full_count >= byte_count) {
    145             break;
    146         }
    147 
    148         ++loop;
    149         if (loop > 10) {
    150             EFUN(USR_DELAY_US(10*timeout_ms));
    151         }
    152         if (loop > 1000) {
    153             return(_error(ERR_CODE_DIAG_TIMEOUT));
    154         }
    155     }
    156     ESTM(*status = rdv_usr_diag_status() & 0xFF);
    157     return(ERR_CODE_NONE);
    158 }
    159 
    160 typedef struct {
    161     uint32_t *buffer_ptr;
    162     } merlin16_read_eye_scan_stripe_callback_arg_t;
    163 
    164 static err_code_t merlin16_read_eye_scan_stripe_callback(void *arg, uint8_t byte_count, uint16_t data) {
    165     merlin16_read_eye_scan_stripe_callback_arg_t * const cast_arg = (merlin16_read_eye_scan_stripe_callback_arg_t *)arg;
    166     *(cast_arg->buffer_ptr++) = merlin16_INTERNAL_float8_to_int32((float8_t)(data & 0xFF));
    167     if (byte_count > 1) {
    168         *(cast_arg->buffer_ptr++) = merlin16_INTERNAL_float8_to_int32((float8_t)(data >> 8));
    169     }
    170     return (ERR_CODE_NONE);
    171 }
    172 
    173 err_code_t merlin16_read_eye_scan_stripe(srds_access_t *sa__, uint32_t *buffer, uint16_t *status) {
    174     merlin16_info_t const * const merlin16_info_ptr = merlin16_INTERNAL_get_merlin16_info_ptr();
    175     const uint8_t lane = merlin16_get_lane(sa__);
    176     const uint8_t stripe_size = 64;
    177 
    178     merlin16_read_eye_scan_stripe_callback_arg_t arg;
    179     uint32_t lane_diag_base;
    180     uint8_t diag_rd_ptr;
    181 
    182     if(!buffer || !status) {
    183         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    184     }
    185     
    186     EFUN(merlin16_INTERNAL_verify_merlin16_info(merlin16_info_ptr, sa__));
    187 
    188         lane_diag_base = merlin16_info_ptr->diag_mem_ram_base + ((lane%merlin16_info_ptr->lane_count) * merlin16_info_ptr->diag_mem_ram_size) + 
    189             merlin16_info_ptr->grp_ram_size*merlin16_INTERNAL_grp_idx_from_lane(merlin16_get_physical_lane(sa__));
    190 
    191     EFUN(merlin16_INTERNAL_poll_diag_data(sa__, merlin16_info_ptr, status, &diag_rd_ptr, stripe_size, 400));
    192         
    193     arg.buffer_ptr = buffer;
    194     EFUN(merlin16_INTERNAL_rdblk_uc_generic_ram(sa__,
    195                                               lane_diag_base,
    196                                               merlin16_info_ptr->diag_mem_ram_size,
    197                                               diag_rd_ptr,
    198                                               stripe_size,
    199                                               &arg,
    200                                               merlin16_read_eye_scan_stripe_callback));
    201 
    202     diag_rd_ptr = ((uint32_t)diag_rd_ptr + stripe_size) % merlin16_info_ptr->diag_mem_ram_size;
    203     EFUN(wrv_usr_diag_rd_ptr(diag_rd_ptr));
    204     ESTM(*status = rdv_usr_diag_status() & 0xFF);
    205     return(ERR_CODE_NONE);
    206 }
    207 
    208 err_code_t merlin16_display_eye_scan_stripe(srds_access_t *sa__, int8_t y,uint32_t *buffer) {
    209 
    210     const uint32_t limits[7] = {917504, 91750, 9175, 917, 91, 9, 1};
    211 
    212     int8_t x,i;
    213     int8_t data_thresh;
    214     int16_t level;
    215 
    216 
    217     ESTM(data_thresh = rd_p1_thresh_sel());
    218     level = merlin16_INTERNAL_ladder_setting_to_mV(sa__, y,data_thresh);
    219 
    220     if(!buffer) {
    221         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    222     }
    223 
    224     EFUN_PRINTF(("%6dmV : ", level));
    225 
    226     for (x=-31;x<32;x++) {
    227         for (i=0;i<7;i++) {
    228             if (buffer[x+31]>=limits[i]) {
    229                 EFUN_PRINTF(("%c", '0'+i+1));
    230                 break;
    231             }
    232         }
    233         if (i==7) {
    234             if      ((x%5)==0 && (y%5)==0) {EFUN_PRINTF(("+"));}
    235             else if ((x%5)!=0 && (y%5)==0) {EFUN_PRINTF(("-"));}
    236             else if ((x%5)==0 && (y%5)!=0) {EFUN_PRINTF((":"));}
    237             else                           {EFUN_PRINTF((" "));}
    238         }
    239     }
    240     return(ERR_CODE_NONE);
    241 }
    242 
    243 err_code_t merlin16_display_eye_scan_header(int8_t i) {
    244 int8_t x;
    245     EFUN_PRINTF(("\n"));
    246     EFUN_PRINTF((" Each character N represents approximate error rate 1e-N at that location\n"));
    247     for(x=1;x<=i;x++) {
    248         EFUN_PRINTF(("  UI/64  : -30  -25  -20  -15  -10  -5    0    5    10   15   20   25   30"));
    249     }
    250     EFUN_PRINTF(("\n"));
    251     for(x=1;x<=i;x++) {
    252         EFUN_PRINTF(("         : -|----|----|----|----|----|----|----|----|----|----|----|----|-"));
    253     }
    254     EFUN_PRINTF(("\n"));
    255     return(ERR_CODE_NONE);
    256 }
    257 
    258 err_code_t merlin16_display_eye_scan_footer(int8_t i) {
    259 int8_t x;
    260     for(x=1;x<=i;x++) {
    261         EFUN_PRINTF(("         : -|----|----|----|----|----|----|----|----|----|----|----|----|-"));
    262     }
    263     EFUN_PRINTF(("\n"));
    264     for(x=1;x<=i;x++) {
    265         EFUN_PRINTF(("  UI/64  : -30  -25  -20  -15  -10  -5    0    5    10   15   20   25   30"));
    266     }
    267     EFUN_PRINTF(("\n"));
    268     return(ERR_CODE_NONE);
    269 }
    270 
    271 
    272 err_code_t merlin16_read_eye_scan_status(srds_access_t *sa__, uint16_t *status) {
    273 
    274    if(!status) {
    275         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    276     }
    277 
    278    ESTM(*status=rdv_usr_diag_status());
    279 
    280     return(ERR_CODE_NONE);
    281 }
    282 
    283 
    284 err_code_t merlin16_meas_eye_scan_done(srds_access_t *sa__) {
    285   EFUN(merlin16_pmd_uc_diag_cmd(sa__, CMD_UC_DIAG_DISABLE,GRACEFUL_STOP_TIME));
    286   return(ERR_CODE_NONE);
    287 }
    288 
    289 
    290 err_code_t merlin16_start_ber_scan_test(srds_access_t *sa__, uint8_t ber_scan_mode, uint8_t timer_control, uint8_t max_error_control) {
    291     uint8_t lock,sts;
    292     ESTM(lock = rd_pmd_rx_lock());
    293     if(lock == 0) {
    294         EFUN_PRINTF(("Error: No PMD_RX_LOCK on lane requesting BER scan\n"));
    295         return(ERR_CODE_DIAG_SCAN_NOT_COMPLETE);
    296     }
    297     ESTM(sts =rdv_usr_sts_micro_stopped());
    298     if(sts > 1) {
    299        EFUN_PRINTF(("Error: Lane is busy (%d) requesting BER scan\n",sts));
    300         return(ERR_CODE_DIAG_SCAN_NOT_COMPLETE);
    301     }
    302 
    303     EFUN(wrcv_diag_max_time_control(timer_control));
    304     EFUN(wrcv_diag_max_err_control(max_error_control));
    305     EFUN(merlin16_pmd_uc_cmd(sa__, CMD_CAPTURE_BER_START, ber_scan_mode,GRACEFUL_STOP_TIME));
    306     return(ERR_CODE_NONE);
    307 }
    308 
    309 err_code_t merlin16_read_ber_scan_data(srds_access_t *sa__, uint32_t *errors, uint32_t *timer_values, uint8_t *cnt, uint32_t timeout) {
    310     uint8_t i,prbs_byte,prbs_multi,time_byte,time_multi;
    311     uint16_t sts,dataword;
    312 
    313 
    314     if(!errors || !timer_values || !cnt) {
    315         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    316     }
    317     /* init data arrays */
    318     for(i=0;i< DIAG_MAX_SAMPLES;i++) {
    319         errors[i]=0;
    320         timer_values[i]=0;
    321     }
    322     /* Check for completion read ln.diag_status byte?*/
    323  ESTM(sts = rdv_usr_diag_status());
    324     if((sts & 0x8000) == 0) {
    325         return(_error(ERR_CODE_DATA_NOTAVAIL));
    326     }
    327     *cnt = (sts & 0x00FF)/3;
    328     for(i=0;i < *cnt;i++) {
    329         /* Read 2 bytes of data */
    330         EFUN(merlin16_pmd_uc_cmd(sa__, CMD_READ_DIAG_DATA_WORD, 0, timeout));
    331         ESTM(dataword = rd_uc_dsc_data());           /* LSB contains 2 -4bit nibbles */
    332         time_byte = (uint8_t)(dataword>>8);          /* MSB is time byte */
    333         prbs_multi = (uint8_t)dataword & 0x0F;       /* split nibbles */
    334         time_multi = (uint8_t)dataword>>4;
    335         /* Read 1 bytes of data */
    336         EFUN(merlin16_pmd_uc_cmd(sa__, CMD_READ_DIAG_DATA_BYTE, 0, timeout));
    337         ESTM(prbs_byte = (uint8_t)rd_uc_dsc_data());
    338         errors[i] = merlin16_INTERNAL_float12_to_uint32(prbs_byte,prbs_multi); /* convert 12bits to uint32 */
    339         timer_values[i] = (merlin16_INTERNAL_float12_to_uint32(time_byte,time_multi)<<3);
    340     /*  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)); */
    341         /*if(timer_values[i] == 0 && errors[i] == 0) break;*/
    342     }
    343 
    344   return(ERR_CODE_NONE);
    345 }
    346 
    347 
    348 /* This is good example function to do BER extrapolation */
    349 err_code_t merlin16_eye_margin_proj(srds_access_t *sa__, USR_DOUBLE rate, uint8_t ber_scan_mode, uint8_t timer_control, uint8_t max_error_control) {
    350     uint32_t errs[DIAG_MAX_SAMPLES];
    351     uint32_t time[DIAG_MAX_SAMPLES];
    352     uint8_t i,cnt=0;
    353     uint16_t sts;
    354     int16_t offset_start;
    355     /* Below 'DIAG_VERBOSE' level is intended to be modified only within a debug */
    356     /* session immediately after a breakpoint, and to retain its state only */
    357     /* through function exit:  therefore it must be 'volatile' to prevent a */
    358     /* compiler from eliding code conditioned on it, but NOT 'static'.      */
    359 
    360 
    361     for(i=0;i<DIAG_MAX_SAMPLES;i++) {
    362         errs[i]=0;
    363         time[i]=0;
    364     }
    365     /* start UC acquisition */
    366     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("start begin\n"));
    367     EFUN(merlin16_start_ber_scan_test(sa__, ber_scan_mode, timer_control, max_error_control));
    368     ESTM(offset_start = rd_uc_dsc_data());
    369     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("offset_start = %d:%dmV\n",offset_start,merlin16_INTERNAL_ladder_setting_to_mV(sa__, (int8_t)offset_start,0)));
    370     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("start done\n"));
    371 
    372     /* This wait is VERY LONG and should be replaced with interupt or something */
    373     if(DIAG_VERBOSE > 5) {
    374         do {
    375           EFUN(USR_DELAY_US(2000000));
    376             ESTM(sts = rdv_usr_diag_status());
    377             EFUN_PRINTF(("sts=%04x\n",sts));
    378 
    379         } while ((sts & 0x8000) == 0);
    380     } else {
    381         EFUN_PRINTF(("Waiting for measurement time approx %d seconds",timer_control+(timer_control>>1)));
    382         EFUN(merlin16_INTERNAL_poll_diag_done(sa__, &sts,timer_control*2000));
    383     }
    384     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("delay done\n"));
    385 
    386     EFUN(merlin16_read_ber_scan_data(sa__, &errs[0], &time[0], &cnt, 2000));
    387 
    388     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("read done cnt=%d\n",cnt));
    389 
    390     EFUN(merlin16_pmd_uc_cmd(sa__, CMD_CAPTURE_BER_END,0x00,200));
    391 
    392     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("end function done\n"));
    393  /* if(cnt == 1) {                                                     */
    394  /*     EFUN_PRINTF(("Not enough points found to extrapolate BER\n")); */
    395  /*     return(ERR_CODE_NONE);                                         */
    396  /* }                                                                  */
    397 
    398     EFUN(merlin16_display_ber_scan_data(sa__, rate, ber_scan_mode, &errs[0], &time[0],(uint8_t)SRDS_ABS(offset_start)));
    399 
    400     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("display done\n"));
    401 
    402     return(ERR_CODE_NONE);
    403 }
    404 
    405 
    406 
    407 err_code_t merlin16_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) {
    408 
    409 #ifdef SERDES_API_FLOATING_POINT
    410     /* 'margins_mv[]' vector maps the p1 threshold code with actual mV
    411         Only relevant when mode=0
    412         This is not totally linear: for code 0~25 step=6mV; code 25~30 step=18mV; code 30~31 step=12
    413         'margins_mv[]' is valid only for Merlin. This vector would need to be modified accordingly for different Serdes
    414     USR_DOUBLE margins_mv[] = {0,6,12,18,24,30,36,42,48,54,60,66,72,78,84,
    415                            90,96,102,108,114,120,126,132,138,144,150,168,186,204,222,240,252};
    416     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,
    417                                         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}; */
    418 #if  !defined(STANDALONE_EVENT)
    419 
    420 
    421     const USR_DOUBLE intrusive_margins_mv[] = {2,6,10,14,18,22,26,30,32,36,40,44,48,52,56,60};
    422 #endif
    423 
    424     const unsigned int HI_CONFIDENCE_ERR_CNT = 100;      /* bit errors */
    425     const unsigned int HI_CONFIDENCE_MIN_ERR_CNT = 20;   /* bit errors */
    426     const unsigned int MAX_CLIPPED_ERR_CNT = 8355840;
    427     const USR_DOUBLE ARTIFICIAL_BER = 0.5;  /* used along ARTIFICIAL_MARGIN(_V/_H) when not enough points to extrapolate */
    428     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 */
    429     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 */
    430     const int MIN_BER_TO_REPORT = -24;   /* we clip the projected BER using this number */
    431     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) */
    432 
    433     /* BER confidence scale */
    434     const USR_DOUBLE ber_conf_scale[104] = {
    435         2.9957,5.5717,3.6123,2.9224,2.5604,2.3337,2.1765,2.0604,1.9704,1.8983,
    436         1.8391,1.7893,1.7468,1.7100,1.6778,1.6494,1.6239,1.6011,1.5804,1.5616,
    437         1.5444,1.5286,1.5140,1.5005,1.4879,1.4762,1.4652,1.4550,1.4453,1.4362,
    438         1.4276,1.4194,1.4117,1.4044,1.3974,1.3908,1.3844,1.3784,1.3726,1.3670,
    439         1.3617,1.3566,1.3517,1.3470,1.3425,1.3381,1.3339,1.3298,1.3259,1.3221,
    440         1.3184,1.3148,1.3114,1.3080,1.3048,1.3016,1.2986,1.2956,1.2927,1.2899,
    441         1.2872,1.2845,1.2820,1.2794,1.2770,1.2746,1.2722,1.2700,1.2677,1.2656,
    442         1.2634,1.2614,1.2593,1.2573,1.2554,1.2535,1.2516,1.2498,1.2481,1.2463,
    443         1.2446,1.2429,1.2413,1.2397,1.2381,1.2365,1.2350,1.2335,1.2320,1.2306,
    444         1.2292,1.2278,1.2264,1.2251,1.2238,1.2225,1.2212,1.2199,1.2187,1.2175,
    445         1.2163, /* starts in index: 100 for #errors: 100,200,300,400 */
    446         1.1486, /* 200 */
    447         1.1198, /* 300 */
    448         1.1030};    /*400 */
    449 
    450 
    451     /* Define variables */
    452     USR_DOUBLE lbers[DIAG_MAX_SAMPLES] = {0};       /* Internal linear scale sqrt(-log(ber)) */
    453     USR_DOUBLE margins[DIAG_MAX_SAMPLES] = {0};     /* Eye margin @ each measurement */
    454     USR_DOUBLE bers[DIAG_MAX_SAMPLES] = {0};        /* computed bit error rate */
    455     uint32_t i;
    456     int8_t offset[DIAG_MAX_SAMPLES];
    457     int8_t mono_flags[DIAG_MAX_SAMPLES];
    458 
    459     int8_t direction;
    460     uint8_t heye;
    461     int8_t delta_n=1;
    462     USR_DOUBLE Exy = 0.0;
    463     USR_DOUBLE Eyy = 0.0;
    464     USR_DOUBLE Exx = 0.0;
    465     USR_DOUBLE Ey  = 0.0;
    466     USR_DOUBLE Ex  = 0.0;
    467     USR_DOUBLE alpha = 0.0;
    468     USR_DOUBLE gauss_noise = -1;
    469     USR_DOUBLE beta = 0.0;
    470     USR_DOUBLE sq_r = 0.0, alpha2 = 0.0;
    471     USR_DOUBLE proj_ber = 0.0, proj_ber_aux = 0.0;
    472     USR_DOUBLE proj_margin_12 = 0.0;
    473     USR_DOUBLE proj_margin_15 = 0.0;
    474     USR_DOUBLE proj_margin_18 = 0.0;
    475     USR_DOUBLE sq_err1 = 0.0, sq_err2 = 0.0;
    476     USR_DOUBLE ierr;
    477     uint8_t start_n;
    478     uint8_t stop_n;
    479     uint8_t low_confidence=1;
    480     uint8_t loop_index;
    481     uint8_t n_mono = 0;
    482     uint8_t eye_cnt;
    483     uint8_t hi_confidence_cnt = 0;
    484     int8_t first_good_ber_idx = -1;
    485     int8_t first_small_errcnt_idx = -1;
    486     int8_t first_non_clipped_errcnt_idx = -1;
    487     uint8_t range250;
    488     uint8_t intrusive;
    489     uint8_t ber_clipped = 0;
    490     uint8_t last_point_discard;
    491     uint8_t fit_count;
    492     int artificial_margin;
    493     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 */
    494     USR_DOUBLE artificial_lber;
    495     char message[256] = "NO MESSAGE";
    496     char unit[5];
    497 
    498     if(!total_errs || !total_time ) {
    499         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    500     }
    501 
    502     /* Initialize BER array */
    503     for (i = 0; i < DIAG_MAX_SAMPLES; i++) {
    504         bers[i] = 0;
    505         mono_flags[i] = 0;
    506     }
    507 
    508     /* Decode mode/direction/etc. */
    509     heye = (ber_scan_mode & DIAG_BER_HORZ)>>1;
    510     direction = (ber_scan_mode & DIAG_BER_NEG) ? -1 : 1 ;
    511     range250 = (ber_scan_mode & DIAG_BER_P1_NARROW) ? 0 : 1;
    512     intrusive = (ber_scan_mode & DIAG_BER_INTR) ? 1 : 0;
    513 
    514     /* Prepare artificial points in case they are needed */
    515     if (heye == 1) {
    516         artificial_margin = direction*ARTIFICIAL_MARGIN_H;
    517     } else {
    518         artificial_margin = direction*ARTIFICIAL_MARGIN_V;
    519     }
    520     artificial_lber = (USR_DOUBLE)sqrt(-log10(ARTIFICIAL_BER));
    521 
    522     /* Printing on-screen message */
    523     if (heye == 1) {
    524         if (direction==-1) EFUN_PRINTF(("\n\n********** HORIZONTAL PROJECTION: LEFT SIDE ******************\n"));
    525         if (direction== 1) EFUN_PRINTF(("\n\n********** HORIZONTAL PROJECTION: RIGHT SIDE *****************\n"));
    526     } else {
    527         if (direction==-1) EFUN_PRINTF(("\n\n********** VERTICAL PROJECTION: BOTTOM ***********************\n"));
    528         if (direction== 1) EFUN_PRINTF(("\n\n********** VERTICAL PROJECTION: TOP **************************\n"));
    529     }
    530 
    531     /* *******************************************
    532         * Generate margins[]
    533         * Generate ber[]
    534         * Find first and last points for linear fit
    535  */
    536     i=0;
    537     do {
    538         if(heye == 1) {
    539             ENULL_STRCPY(unit,"mUI");
    540             offset[i] = (int8_t)(max_offset-i);
    541 #ifndef STANDALONE_EVENT
    542             margins[i] = direction*offset[i]*1000.0/64.0;
    543 #else
    544             margins[i] = info_out->margins[i];
    545 #endif
    546         } else {
    547             ENULL_STRCPY(unit,"mV");
    548             offset[i] = (int8_t)(max_offset-i);
    549 #ifndef STANDALONE_EVENT
    550             if(intrusive) {
    551                 margins[i] = direction*intrusive_margins_mv[offset[i]];
    552             } else {
    553                 margins[i] = direction*merlin16_INTERNAL_ladder_setting_to_mV(sa__, offset[i], range250);
    554             }
    555 #else
    556             margins[i] = info_out->margins[i];
    557 #endif
    558         }
    559         if (total_errs[i] == 0) {
    560             bers[i] = 1.0/(((USR_DOUBLE)total_time[i])*0.00001*rate);
    561         } else {
    562             bers[i] = (USR_DOUBLE)total_errs[i]/(((USR_DOUBLE)total_time[i])*0.00001*rate);
    563         }
    564 
    565         /* Find the first data point with good BER (BER <= 10^MIN_BER_FOR_FIT)
    566         NOTE: no need for lower bound on BER, since correction factors will be applied for all total_errs>=0 */
    567         if ((log10(bers[i]) <= MIN_BER_FOR_FIT) && (first_good_ber_idx == -1)) {
    568             first_good_ber_idx = (int8_t)i;
    569         }
    570 
    571         /* Determine high-confidence iterations */
    572         if (total_errs[i] >= HI_CONFIDENCE_ERR_CNT) {
    573             hi_confidence_cnt++;
    574         } else if ((total_errs[i] < HI_CONFIDENCE_MIN_ERR_CNT) && (first_small_errcnt_idx == -1)) {
    575             /* find the first data point with small error count */
    576             first_small_errcnt_idx = (int8_t)i;
    577         }
    578 
    579         /* Determine first NON-clipped error count
    580             NOTE: Originally this limit was created for post processing of micro-generated data; however, this could be used for PC-generated data as well */
    581         if ((total_errs[i] < MAX_CLIPPED_ERR_CNT) && (first_non_clipped_errcnt_idx == -1) ) {
    582             first_non_clipped_errcnt_idx = (int8_t)i;
    583         }
    584 
    585       i++;
    586 
    587     } while(((total_errs[i] != 0) || (total_time[i] != 0)) && (i<=max_offset));
    588 
    589     eye_cnt = (int8_t) i;
    590 
    591 
    592     /* *******************************************
    593     Setting up stop_n variable.
    594     Check if:
    595         - There is only one point in measurement vector (i.e. eye_cnt = 1)
    596         - The very last point's measurement time was "too short"
    597  */
    598 
    599     i = eye_cnt - 1;
    600     if (i>=1) {
    601         if ((total_time[i] >= 0.5*total_time[i-1]) || (total_errs[i] >= HI_CONFIDENCE_MIN_ERR_CNT) ){
    602             stop_n = eye_cnt;   /* last point will be included in linear fit */
    603             last_point_discard = 0;
    604         } else {
    605             stop_n = eye_cnt - 1;   /* discards the very last point */
    606             last_point_discard = 1;
    607         }
    608     } else {
    609         stop_n = 1; /* there is ONLY one measurement */
    610         last_point_discard = 0;
    611     }
    612 
    613 
    614     /* *******************************************
    615     Print on screen (prints RAW BER data. i.e. conf factors)
    616  */
    617     i = 0;
    618     do {
    619         if (total_errs[i] == 0) {
    620            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));
    621         } else if (total_errs[i] >= MAX_CLIPPED_ERR_CNT) {
    622            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));
    623         } else {
    624            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));
    625         }
    626         i++;
    627     } while (i<stop_n);
    628 
    629     /* *******************************************
    630     Correcting *all* BER values using confidence factors in 'ber_conf_scale' vector
    631     This step is done for extrapolation purposes
    632  */
    633     for (loop_index=0; loop_index < eye_cnt; loop_index++) {
    634         if (total_errs[loop_index] <= 100) {
    635             bers[loop_index] = ber_conf_scale[total_errs[loop_index]] * bers[loop_index];
    636         } else if (total_errs[loop_index] > 100 && total_errs[loop_index] < 200) {
    637             bers[loop_index] = ber_conf_scale[100] * bers[loop_index];
    638         } else if (total_errs[loop_index] >= 200 && total_errs[loop_index] < 300) {
    639             bers[loop_index] = ber_conf_scale[101] * bers[loop_index];
    640         } else if (total_errs[loop_index] >= 300 && total_errs[loop_index] < 400) {
    641             bers[loop_index] = ber_conf_scale[102] * bers[loop_index];
    642         } else if (total_errs[loop_index] >= 400) {
    643             bers[loop_index] = ber_conf_scale[103] * bers[loop_index];
    644         }
    645     }
    646 
    647     /* *******************************************
    648     Computes the "linearised" ber vector
    649  */
    650     for (loop_index=0; loop_index<eye_cnt; loop_index++) {
    651         lbers[loop_index] = (USR_DOUBLE)sqrt(-log10(bers[loop_index]));
    652     }
    653 
    654     /* *******************************************
    655     Assign highest data point to use
    656  */
    657     if (first_good_ber_idx == -1) {
    658         start_n = stop_n;
    659     } else {
    660         start_n = first_good_ber_idx;
    661     }
    662 
    663 
    664 
    665     /* ******************************************************
    666     ***********  EXTRAPOLATION (START) **********************
    667     *********************************************************
    668     Different data set profiles can be received by this code.
    669     Each case is processed accordingly here (IF-ELSE IF cases)
    670  */
    671 
    672     /* ====> Errors encountered all the way to sampling point */
    673     if (start_n >= eye_cnt) {
    674         proj_case = 1;
    675         ENULL_STRCPY(message,"No low-BER point measured");
    676 
    677         /* confidence factor of 0.96 is applied in this case to set a LOWER bound and report accordingly.
    678             This factor corresponds to approximately 3000 errors @95% confidence
    679             For reference: factors for 900, 2000, 3000, 5000, 20000 and 50000 errors are: 0.96, 0.96, 0.97, 0.99, 0.99, respectively */
    680         proj_ber = 0.96*log10(bers[eye_cnt-1]);
    681         proj_ber_aux = proj_ber;
    682         EFUN_PRINTF(("BER *worse* than 1e%0.2f\n", proj_ber));
    683         EFUN_PRINTF(("No margin @ 1e-12, 1e-15 & 1e-18\n\n\n"));
    684         fit_count = 1;
    685     }
    686 
    687     else {
    688 
    689         /* ====> Only ONE measured point. Typically when the eye is wide open.
    690             Artificial points will be used to make extrapolation possible */
    691         if (stop_n==1) {
    692             proj_case = 2;
    693             ENULL_STRCPY(message,"Not enough points (single measured point). Using artificial point");
    694 
    695             low_confidence = 1;
    696             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 */
    697             fit_count = 2;
    698 
    699             /* Compute covariances and means... but only for two points: artificial and the single measured point */
    700             Exy = ((margins[0]*lbers[0] + artificial_margin*artificial_lber)/2.0);
    701             Eyy = ((lbers[0]*lbers[0] + artificial_lber*artificial_lber)/2.0);
    702             Exx = ((margins[0]*margins[0] + artificial_margin*artificial_margin)/2.0);
    703             Ey  = ((lbers[0] + artificial_lber)/2.0);
    704             Ex  = ((margins[0] + artificial_margin)/2.0);
    705         }
    706 
    707         /* ====> "NORMAL" case (when there are more than 1 measurements) */
    708         else {
    709 
    710             /* Detect and record nonmonotonic data points */
    711             for (loop_index=0; loop_index < stop_n; loop_index++) {
    712                 if ((loop_index > start_n) && (log10(bers[loop_index]) > log10(bers[loop_index-1]))) {
    713                     mono_flags[loop_index] = 1;
    714                     if (first_good_ber_idx != -1) {
    715                         n_mono++;
    716                     }
    717                 }
    718             }
    719 
    720             /* Finds number of MEASURED points available for extrapolation */
    721             delta_n = (stop_n-start_n-n_mono);
    722 
    723 
    724             /*  HIGH CONFIDENCE case */
    725 
    726             if (delta_n >= 2) { /* there are at least 2 points to trace a line */
    727                 proj_case = 3;
    728                 ENULL_STRCPY(message,"Normal case");
    729                 low_confidence = 0;
    730 
    731                 /* Compute covariances and means */
    732                 fit_count = 0;
    733                 for (loop_index=start_n; loop_index < stop_n; loop_index++) {
    734                     if (mono_flags[loop_index] == 0) {
    735                         Exy += (margins[loop_index]*lbers[loop_index]/(USR_DOUBLE)delta_n);
    736                         Eyy += (lbers[loop_index]*lbers[loop_index]/(USR_DOUBLE)delta_n);
    737                         Exx += (margins[loop_index]*margins[loop_index]/(USR_DOUBLE)delta_n);
    738                         Ey  += (lbers[loop_index]/(USR_DOUBLE)delta_n);
    739                         Ex  += (margins[loop_index]/(USR_DOUBLE)delta_n);
    740                         fit_count++;
    741                     }
    742                 }
    743             }
    744 
    745             /*  LOW CONFIDENCE case */
    746 
    747             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 */
    748                 low_confidence = 1;
    749                 if ( (first_non_clipped_errcnt_idx>=0) && (first_non_clipped_errcnt_idx < start_n)) {
    750                     proj_case = 4;
    751                     ENULL_STRCPY(message,"Not enough points. Using first measured point for conservative estimation");
    752                     fit_count = 2;
    753                     /* Compute covariances and means... but only for two points: first and last */
    754                     Exy = ((margins[stop_n-1]*lbers[stop_n-1] + margins[first_non_clipped_errcnt_idx]*lbers[first_non_clipped_errcnt_idx])/2.0);
    755                     Eyy = ((lbers[stop_n-1]*lbers[stop_n-1] + lbers[first_non_clipped_errcnt_idx]*lbers[first_non_clipped_errcnt_idx])/2.0);
    756                     Exx = ((margins[stop_n-1]*margins[stop_n-1] + margins[first_non_clipped_errcnt_idx]*margins[first_non_clipped_errcnt_idx])/2.0);
    757                     Ey  = ((lbers[stop_n-1] + lbers[first_non_clipped_errcnt_idx])/2.0);
    758                     Ex  = ((margins[stop_n-1] + margins[first_non_clipped_errcnt_idx])/2.0);
    759                 } else {
    760                     proj_case = 5;
    761                     ENULL_STRCPY(message,"Not enough points (cannot use non-clipped ErrorCount point). Using artificial point");
    762                     /* Compute covariances and means... but only for two points: artificial and the single measured point */
    763                     Exy = (artificial_margin*artificial_lber)/2.0;
    764                     Eyy = (artificial_lber*artificial_lber)/2.0;
    765                     Exx = (artificial_margin*artificial_margin)/2.0;
    766                     Ey  = (artificial_lber)/2.0;
    767                     Ex  = (artificial_margin)/2.0;
    768                     fit_count = 1;
    769                     /* This FOR loop checks for monotonicity as well */
    770                     for (loop_index=start_n; loop_index < stop_n; loop_index++) {
    771                         if (mono_flags[loop_index] == 0) {
    772                             Exy += (margins[loop_index]*lbers[loop_index]/2.0);
    773                             Eyy += (lbers[loop_index]*lbers[loop_index]/2.0);
    774                             Exx += (margins[loop_index]*margins[loop_index]/2.0);
    775                             Ey  += (lbers[loop_index]/2.0);
    776                             Ex  += (margins[loop_index]/2.0);
    777                             fit_count++;
    778                         }
    779                     }
    780                 }
    781             }
    782         }
    783 
    784         /* Compute fit slope and offset: ber = alpha*margin + beta */
    785         alpha = (Exy - Ey*Ex) / (Exx - Ex*Ex);
    786         beta = Ey - Ex*alpha;
    787         /* Compute alpha2: slope of regression: margin = alpha2*ber + beta2 */
    788         alpha2 = (Exy - Ey*Ex) / (Eyy - Ey*Ey);
    789         /* Compute correlation index sq_r */
    790         sq_r = alpha*alpha2;
    791 
    792         proj_ber = pow(10,(-beta*beta));
    793         proj_margin_12 = direction*(sqrt(-log10(1e-12))-beta)/alpha;
    794         proj_margin_15 = direction*(sqrt(-log10(1e-15))-beta)/alpha;
    795         proj_margin_18 = direction*(sqrt(-log10(1e-18))-beta)/alpha;
    796 
    797         /* Estimate modeled gaussian noise.
    798         
    799             The following is based on the Q-function model and the following table:
    800                 Q    |    log10(BER)
    801             =======================
    802               7.033    |    -12
    803               7.941    |    -15
    804               8.757    |    -18
    805               
    806         Based on the above, we solve for sigma:
    807             7.033*sigma = u - proj_margin_12 , and
    808             7.941*sigma = u - proj_margin_15
    809         */
    810         gauss_noise = (proj_margin_12 - proj_margin_15)/0.908;
    811         
    812         sq_err1 = (Eyy + (beta*beta) + (Exx*alpha*alpha) -
    813                    (2*Ey*beta) - (2*Exy*alpha) + (2*Ex*beta*alpha));
    814         sq_err2 = 0;
    815         for (loop_index=start_n; loop_index<stop_n; loop_index++) {
    816             ierr = (lbers[loop_index] - (alpha*margins[loop_index] + beta));
    817             sq_err2 += (ierr*ierr/(USR_DOUBLE)delta_n);
    818         }
    819 
    820         proj_ber = log10(proj_ber);
    821         proj_ber_aux = proj_ber;
    822 
    823         if (proj_ber < MIN_BER_TO_REPORT) {
    824             proj_ber = MIN_BER_TO_REPORT;
    825             ber_clipped = 1;
    826         }
    827 
    828         /* Extrapolated results, low confidence */
    829         if (low_confidence == 1) {
    830 
    831             EFUN_PRINTF(("BER(extrapolated) < 1e%0.2f\n", proj_ber));
    832             EFUN_PRINTF(("Margin @ 1e-12    > %0.2f %s\n", (proj_ber < -12)? SRDS_ABS(proj_margin_12) : 0, unit));
    833             EFUN_PRINTF(("Margin @ 1e-15    > %0.2f %s\n", (proj_ber < -15)? SRDS_ABS(proj_margin_15) : 0, unit));
    834             EFUN_PRINTF(("Margin @ 1e-18    > %0.2f %s\n", (proj_ber < -18)? SRDS_ABS(proj_margin_18) : 0, unit));
    835 
    836         /* Extrapolated results, HIGH confidence */
    837         } else {
    838 
    839             if (ber_clipped == 1) {
    840                 EFUN_PRINTF(("BER(extrapolated) < 1e%0.2f\n", proj_ber));
    841             } else {
    842                 EFUN_PRINTF(("BER(extrapolated) = 1e%0.2f\n", proj_ber));
    843             }
    844             EFUN_PRINTF(("Margin @ 1e-12    = %0.2f %s\n", (proj_ber < -12)? SRDS_ABS(proj_margin_12) : 0, unit));
    845             EFUN_PRINTF(("Margin @ 1e-15    = %0.2f %s\n", (proj_ber < -15)? SRDS_ABS(proj_margin_15) : 0, unit));
    846             EFUN_PRINTF(("Margin @ 1e-18    = %0.2f %s\n", (proj_ber < -18)? SRDS_ABS(proj_margin_18) : 0, unit));
    847         }
    848 
    849         EFUN_PRINTF(("\n\n"));
    850 
    851         /* Print non-monotonic outliers */
    852         if (n_mono != 0) {
    853             EFUN_PRINTF(("Detected non-monotonicity at { "));
    854             for (loop_index = start_n; loop_index < stop_n; loop_index++) {
    855                 if (mono_flags[loop_index] == 1) {
    856                     EFUN_PRINTF(("%0.2f ", margins[loop_index]));
    857                 }
    858             }
    859             EFUN_PRINTF(("} %s\n\n\n",unit));
    860         }
    861 
    862     }
    863     /* *******************************************
    864     ***********  EXTRAPOLATION (END) *************
    865  */
    866 
    867 
    868 
    869     /* SUMMARY (for debugging purposes */
    870     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("\t=====> DEBUG INFO (start)\n\n"));
    871     if (DIAG_VERBOSE > 2) {
    872         EFUN_PRINTF((" loop   Margin      total_errors   time(sec)  logBER       lber"));
    873         for (loop_index=0; loop_index < stop_n+last_point_discard; loop_index++) {
    874             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]));
    875         }
    876         EFUN_PRINTF(("\n\n"));
    877     }
    878     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("Max Offset = %d\n",max_offset));
    879     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("ber_clipped: %d, Projected BER (proj_ber_aux) = %.2f\n", ber_clipped, proj_ber_aux));
    880     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)));
    881     {
    882         char aux_str[20];
    883         USR_SPRINTF(aux_str, "%d", total_errs[first_small_errcnt_idx]);
    884         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")));
    885     }
    886     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",
    887                 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));
    888     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));
    889     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("%s\n", message));
    890     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("proj_case %d\n",proj_case));
    891     if (DIAG_VERBOSE > 2) EFUN_PRINTF(("\n\t=====> DEBUG INFO (end)\n\n"));
    892     EFUN_PRINTF(("\n\n\n"));
    893 
    894 
    895 #else
    896     (void)rate;
    897     (void)ber_scan_mode;
    898     (void)max_offset;
    899 
    900     EFUN_PRINTF(("This function needs SERDES_API_FLOATING_POINT define to operate \n"));
    901 
    902     if(!total_errs || !total_time ) {
    903         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    904     }
    905 #endif
    906     return(ERR_CODE_NONE);
    907 }
    908 
    909 /*****************************/
    910 /*  Display Lane/Core State  */
    911 /*****************************/
    912 
    913 err_code_t merlin16_display_lane_state_hdr(void) {
    914   EFUN_PRINTF(("LN (CDRxN  , UC_CFG,UC_STS,TX_RX_RST,STP) "));
    915   EFUN_PRINTF(("SD LCK RXPPM "));
    916   EFUN_PRINTF(("CLK90 CLKP1 "));
    917   EFUN_PRINTF(("PF(M,L) "));
    918   EFUN_PRINTF(("VGA "));
    919   EFUN_PRINTF(("DCO P1mV "));
    920   EFUN_PRINTF((" DFE(1,2,3,4,5,dcd1,dcd2)   SLICER(ze,zo,pe,po,me,mo) "));
    921   EFUN_PRINTF(("TXPPM TXEQ(n1,m,p1,p2) EYE(L,R,U,D) "));
    922   EFUN_PRINTF(("SOC(p,n) "));
    923   EFUN_PRINTF(("LINK_TIME    BER"));
    924   EFUN_PRINTF(("\n"));
    925   return (ERR_CODE_NONE);
    926 }
    927 
    928 err_code_t merlin16_display_lane_state_legend(void) {
    929   EFUN_PRINTF(("\n"));
    930   EFUN_PRINTF(("**********************************************************************************************\n"));
    931   EFUN_PRINTF(("****                Legend of Entries in display_lane_state()                             ****\n"));
    932   EFUN_PRINTF(("**********************************************************************************************\n"));
    933   EFUN_PRINTF(("LN        : Lane index within IP core\n"));
    934   EFUN_PRINTF(("CDRxN     : CDR type x OSR ratio [xT-OS3p3; x7-OS7p5; x9-OSx8p25; xA-OSx10]\n"));
    935   EFUN_PRINTF(("UC_CFG    : Micro lane configuration variable\n"));
    936   EFUN_PRINTF(("UC_STS    : Micro lane status variable\n"));
    937 #if defined(SERDES_TX_RS_SEPARATE)
    938   EFUN_PRINTF(("TX_RX_RST : TX and RX Reset State{reset_active, reset_occured, reset_held}\n"));
    939 #else
    940   EFUN_PRINTF(("RST       : Reset State{reset_active, reset_occured, reset_held}\n"));
    941 #endif
    942   EFUN_PRINTF(("STP       : uC Stopped State\n"));
    943   EFUN_PRINTF(("SD        : Signal Detect\n"));
    944   EFUN_PRINTF(("LCK       : pmd_rx_lock\n"));
    945   EFUN_PRINTF(("RXPPM     : Frequency offset of local reference clock with respect to RX data in ppm\n"));
    946   EFUN_PRINTF(("CLK90     : Delay of zero crossing slicer, m1, wrt to data in PI codes\n"));
    947   EFUN_PRINTF(("CLKP1     : Delay of diagnostic/lms slicer, p1, wrt to data in PI codes\n"));
    948   EFUN_PRINTF(("PF(M,L)   : Peaking Filter Main (0..15) and Low Frequency (0..7) settings\n"));
    949 #if defined(RX_VGA_CTRL_VAL_MIN)
    950   EFUN_PRINTF(("VGA       : Variable Gain Amplifier settings (%d..%d)\n", RX_VGA_CTRL_VAL_MIN, RX_VGA_CTRL_VAL_MAX));
    951 #else
    952   EFUN_PRINTF(("VGA       : Variable Gain Amplifier settings (0..%d)\n", RX_VGA_CTRL_VAL_MAX));
    953 #endif
    954   EFUN_PRINTF(("DCO       : DC offset DAC control value\n"));
    955   EFUN_PRINTF(("P1mV      : Vertical threshold voltage of p1 slicer\n"));
    956   EFUN_PRINTF(("DFE taps  : ISI correction taps in units of 2.35mV (for 1 & 2 even values are displayed, dcd = even-odd)\n"));
    957   EFUN_PRINTF(("SLICER(ze,zo,pe,po,me,mo) : Slicer calibration control codes\n"));
    958   EFUN_PRINTF(("TXPPM     : Frequency offset of local reference clock with respect to TX data in ppm\n"));
    959   EFUN_PRINTF(("TXEQ(n1,m,p1,p2) : TX equalization FIR tap weights in units of 1Vpp/60 units\n"));
    960   EFUN_PRINTF(("SOC(p,n)  : Signal Detect Offset Calibration\n"));
    961   EFUN_PRINTF(("EYE(L,R,U,D) : Eye margin @ 1e-5 as seen by internal diagnostic slicer in mUI and mV\n"));
    962   EFUN_PRINTF(("LINK_TIME : Link time in milliseconds\n"));
    963   EFUN_PRINTF(("BER : Bit Error Rate calculated based on 100ms test time; displayed only if prbs_chk_en=1.\n"));
    964   EFUN_PRINTF(("**********************************************************************************************\n"));
    965   return (ERR_CODE_NONE);
    966 }
    967 
    968 err_code_t merlin16_display_lane_state(srds_access_t *sa__) {
    969   err_code_t err_code = merlin16_INTERNAL_display_lane_state_no_newline(sa__);
    970   EFUN_PRINTF(("\n"));
    971   return (err_code);
    972 }
    973 
    974 err_code_t merlin16_display_core_state_hdr(void) {
    975     char core_type[20] = "merlin16";          
    976     COMPILER_REFERENCE(core_type); 
    977     EFUN_PRINTF(("SerDes type = %s\n",core_type));
    978 
    979   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  PLL_DIV  PLL_LOCK"));
    980   EFUN_PRINTF(("\n"));
    981   return (ERR_CODE_NONE);
    982 }
    983 
    984 err_code_t merlin16_display_core_state_line(srds_access_t *sa__) {
    985   err_code_t err_code = merlin16_INTERNAL_display_core_state_no_newline(sa__);
    986   EFUN_PRINTF(("\n"));
    987   return (err_code);
    988 }
    989 
    990 err_code_t merlin16_display_core_state_legend(void) {
    991   EFUN_PRINTF(("\n"));
    992   EFUN_PRINTF(("**************************************************************************************************************\n"));
    993   EFUN_PRINTF(("****                          Legend of Entries in display_core_state()                                   ****\n"));
    994   EFUN_PRINTF(("**************************************************************************************************************\n"));
    995   EFUN_PRINTF(("*  RST_ST           : Core DP Reset State{reset_active, reset_occured, reset_held}, Core uC Status byte(hex) *\n"));
    996   EFUN_PRINTF(("*  PLL_PWDN         : PLL Powerdown Control Bit (active high)                                                *\n"));
    997   EFUN_PRINTF(("*  UC_ATV           : UC Active bit                                                                          *\n"));
    998   EFUN_PRINTF(("*  COM_CLK          : COM Clock frequency in MHz                                                             *\n"));
    999   EFUN_PRINTF(("*  UCODE_VER        : Microcode Version [majorversion_minorversion]                                          *\n"));
   1000   EFUN_PRINTF(("*  API_VER          : API Version                                                                            *\n"));
   1001   EFUN_PRINTF(("*  AFE_VER          : AFE Hardware Vesrion                                                                   *\n"));
   1002   EFUN_PRINTF(("*  LIVE_TEMP        : Live Die temperature in Celsius                                                        *\n"));
   1003   EFUN_PRINTF(("*  AVG_TMON         : uC Temp_idx, Average temperature in Celsius                                            *\n"));
   1004   EFUN_PRINTF(("*  RESCAL           : Analog Resistor Calibration value                                                      *\n"));
   1005   EFUN_PRINTF(("*  VCO_RATE         : uC VCO Rate in GHz (approximate)                                                       *\n"));
   1006   EFUN_PRINTF(("*  ANA_VCO_RANGE    : Analog VCO Range                                                                       *\n"));
   1007   EFUN_PRINTF(("*  PLL_Lock         : PLL Lock                                                                               *\n"));
   1008 
   1009   EFUN_PRINTF(("**************************************************************************************************************\n"));
   1010   return (ERR_CODE_NONE);
   1011 }
   1012 
   1013 /**********************************************/
   1014 /*  Display Lane/Core Config and Debug Status */
   1015 /**********************************************/
   1016 err_code_t merlin16_display_core_config(srds_access_t *sa__) {
   1017     EFUN_PRINTF(("\n\n***********************************\n"  ));
   1018     EFUN_PRINTF((    "**** SERDES CORE CONFIGURATION ****\n"  ));
   1019     EFUN_PRINTF((    "***********************************\n\n"));
   1020     {
   1021         struct   merlin16_uc_core_config_st core_cfg;
   1022         ENULL_MEMSET(&core_cfg, 0, sizeof(core_cfg));
   1023             EFUN(merlin16_get_uc_core_config(sa__, &core_cfg));
   1024         {
   1025             uint16_t  vco_mhz = (uint16_t)core_cfg.vco_rate_in_Mhz;
   1026             COMPILER_REFERENCE(vco_mhz);
   1027     EFUN_PRINTF((    "uC Config VCO Rate   = %d (~%d.%03dGHz)\n"                  , core_cfg.field.vco_rate
   1028                                                                                   , (vco_mhz / 1000)
   1029                                                                                   , (vco_mhz % 1000)                ));
   1030     EFUN_PRINTF((    "Core Config from PCS = %d\n\n"                              , core_cfg.field.core_cfg_from_pcs));
   1031         }
   1032     }
   1033     ESTM_PRINTF((    "Tx Lane Addr 0       = %d\n"                                , rdc_tx_lane_addr_0()));
   1034     ESTM_PRINTF((    "Rx Lane Addr 0       = %d\n"                                , rdc_rx_lane_addr_0()));
   1035     ESTM_PRINTF((    "Tx Lane Addr 1       = %d\n"                                , rdc_tx_lane_addr_1()));
   1036     ESTM_PRINTF((    "Rx Lane Addr 1       = %d\n"                                , rdc_rx_lane_addr_1()));
   1037     ESTM_PRINTF((    "Tx Lane Addr 2       = %d\n"                                , rdc_tx_lane_addr_2()));
   1038     ESTM_PRINTF((    "Rx Lane Addr 2       = %d\n"                                , rdc_rx_lane_addr_2()));
   1039     ESTM_PRINTF((    "Tx Lane Addr 3       = %d\n"                                , rdc_tx_lane_addr_3()));
   1040     ESTM_PRINTF((    "Rx Lane Addr 3       = %d\n"                                , rdc_rx_lane_addr_3()));
   1041 #ifdef rdc_tx_lane_addr_4
   1042     ESTM_PRINTF((    "Tx Lane Addr 4       = %d\n"                                , rdc_tx_lane_addr_4()));
   1043     ESTM_PRINTF((    "Rx Lane Addr 4       = %d\n"                                , rdc_rx_lane_addr_4()));
   1044 #endif
   1045 #ifdef rdc_tx_lane_addr_5
   1046     ESTM_PRINTF((    "Tx Lane Addr 5       = %d\n"                                , rdc_tx_lane_addr_5()));
   1047     ESTM_PRINTF((    "Rx Lane Addr 5       = %d\n"                                , rdc_rx_lane_addr_5()));
   1048 #endif
   1049 #ifdef rdc_tx_lane_addr_6
   1050     ESTM_PRINTF((    "Tx Lane Addr 6       = %d\n"                                , rdc_tx_lane_addr_6()));
   1051     ESTM_PRINTF((    "Rx Lane Addr 6       = %d\n"                                , rdc_rx_lane_addr_6()));
   1052 #endif
   1053 #ifdef rdc_tx_lane_addr_7
   1054     ESTM_PRINTF((    "Tx Lane Addr 7       = %d\n"                                , rdc_tx_lane_addr_7()));
   1055     ESTM_PRINTF((    "Rx Lane Addr 7       = %d\n"                                , rdc_rx_lane_addr_7()));
   1056 #endif
   1057     return(ERR_CODE_NONE);
   1058 }
   1059 
   1060 
   1061 err_code_t merlin16_display_lane_config(srds_access_t *sa__) {
   1062     struct merlin16_uc_lane_config_st lane_cfg;
   1063 
   1064     ENULL_MEMSET(&lane_cfg, 0, sizeof(lane_cfg));
   1065 
   1066     EFUN_PRINTF(("\n\n*************************************\n"                                          ));
   1067     ESTM_PRINTF((   "**** SERDES LANE %d CONFIGURATION ****\n"  , merlin16_get_lane(sa__)                 ));
   1068     EFUN_PRINTF((    "*************************************\n\n"                                        ));
   1069     EFUN(                                                         merlin16_get_uc_lane_cfg(sa__, &lane_cfg));
   1070     EFUN_PRINTF((    "Lane Config from PCS        = %d\n\n"     , lane_cfg.field.lane_cfg_from_pcs      ));
   1071     EFUN_PRINTF((    "Auto-Neg Enabled            = %d\n"       , lane_cfg.field.an_enabled             ));
   1072     EFUN_PRINTF((    "DFE on                      = %d\n"       , lane_cfg.field.dfe_on                 ));
   1073     EFUN_PRINTF((    "Brdfe_on                    = %d\n"       , lane_cfg.field.force_brdfe_on         ));
   1074     EFUN_PRINTF((    "Media Type                  = %d\n"       , lane_cfg.field.media_type             ));
   1075     EFUN_PRINTF((    "Unreliable LOS              = %d\n"       , lane_cfg.field.unreliable_los         ));
   1076     EFUN_PRINTF((    "Scrambling Disable          = %d\n"       , lane_cfg.field.scrambling_dis         ));
   1077     ESTM_PRINTF((    "CL72 Training        Enable = %d\n"       , rd_cl72_ieee_training_enable()        ));
   1078     EFUN_PRINTF((    "CL72 Auto Polarity   Enable = %d\n"       , lane_cfg.field.cl72_auto_polarity_en  ));
   1079     EFUN_PRINTF((    "CL72 Restart timeout Enable = %d\n"       , lane_cfg.field.cl72_restart_timeout_en));
   1080 
   1081     ESTM_PRINTF((    "TX OSR Mode Force           = %d\n"       , rd_tx_osr_mode_frc()                  ));
   1082     ESTM_PRINTF((    "TX OSR Mode Force Val       = %d\n"       , rd_tx_osr_mode_frc_val()              ));
   1083     ESTM_PRINTF((    "RX OSR Mode Force           = %d\n"       , rd_rx_osr_mode_frc()                  ));
   1084     ESTM_PRINTF((    "RX OSR Mode Force Val       = %d\n"       , rd_rx_osr_mode_frc_val()              ));
   1085     ESTM_PRINTF((    "TX Polarity Invert          = %d\n"       , rd_tx_pmd_dp_invert()                 ));
   1086     ESTM_PRINTF((    "RX Polarity Invert          = %d\n\n"     , rd_rx_pmd_dp_invert()                 ));
   1087     ESTM_PRINTF((    "TXFIR Post2                 = %d\n"       , rd_txfir_post2()                      ));
   1088     ESTM_PRINTF((    "TXFIR Main Override         = %d\n"       , rd_cl72_txfir_main()                  ));
   1089     ESTM_PRINTF((    "TXFIR Pre Override          = %d\n"       , rd_cl72_txfir_pre()                   ));
   1090     ESTM_PRINTF((    "TXFIR Post Override         = %d\n"       , rd_cl72_txfir_post()                  ));
   1091     return(ERR_CODE_NONE);
   1092 }
   1093 
   1094 
   1095 err_code_t merlin16_display_core_state(srds_access_t *sa__) {
   1096     EFUN(merlin16_display_core_state_hdr());
   1097     EFUN(merlin16_display_core_state_line(sa__));
   1098     EFUN(merlin16_display_core_state_legend());
   1099     return ERR_CODE_NONE;
   1100 }
   1101 
   1102 
   1103 err_code_t merlin16_display_lane_debug_status(srds_access_t *sa__) {
   1104     /* startup */
   1105     struct merlin16_usr_ctrl_disable_functions_st     ds;
   1106     struct merlin16_usr_ctrl_disable_dfe_functions_st dsd;
   1107     /* steady state */
   1108     struct merlin16_usr_ctrl_disable_functions_st     dss;
   1109     struct merlin16_usr_ctrl_disable_dfe_functions_st dssd;
   1110 
   1111     ENULL_MEMSET(&ds  , 0, sizeof(ds  ));
   1112     ENULL_MEMSET(&dsd , 0, sizeof(dsd ));
   1113     ENULL_MEMSET(&dss , 0, sizeof(dss ));
   1114     ENULL_MEMSET(&dssd, 0, sizeof(dssd));
   1115 
   1116     EFUN_PRINTF(("\n\n************************************\n"                                                     ));
   1117     ESTM_PRINTF((   "**** SERDES LANE %d DEBUG STATUS ****\n"               , merlin16_get_lane(sa__)               ));
   1118     EFUN_PRINTF((    "************************************\n\n"                                                   ));
   1119     ESTM_PRINTF((    "Restart Count                                = %d\n"  , rdv_usr_sts_restart_counter()       ));
   1120     ESTM_PRINTF((    "Reset Count                                  = %d\n"  , rdv_usr_sts_reset_counter()         ));
   1121     ESTM_PRINTF((    "PMD Lock Count                               = %d\n\n", rdv_usr_sts_pmd_lock_counter()      ));
   1122     EFUN(merlin16_get_usr_ctrl_disable_startup(sa__, &ds));
   1123     EFUN_PRINTF((    "Disable Startup PF Adaptation                = %d\n"  , ds.field.pf_adaptation              ));
   1124     EFUN_PRINTF((    "Disable Startup DC Adaptation                = %d\n"  , ds.field.dc_adaptation              ));
   1125     EFUN_PRINTF((    "Disable Startup Slicer Offset Tuning         = %d\n"  , ds.field.slicer_offset_tuning       ));
   1126     EFUN_PRINTF((    "Disable Startup Clk90 offset Adaptation      = %d\n"  , ds.field.clk90_offset_adaptation    ));
   1127     EFUN_PRINTF((    "Disable Startup P1 level Tuning              = %d\n"  , ds.field.p1_level_tuning            ));
   1128     EFUN_PRINTF((    "Disable Startup Eye Adaptation               = %d\n"  , ds.field.eye_adaptation             ));
   1129     EFUN_PRINTF((    "Disable Startup All Adaptation               = %d\n\n", ds.field.all_adaptation             ));
   1130     EFUN(                                                            merlin16_get_usr_ctrl_disable_startup_dfe(sa__, &dsd));
   1131     EFUN_PRINTF((    "Disable Startup DFE Tap1 Adaptation          = %d\n"  , dsd.field.dfe_tap1_adaptation       ));
   1132     EFUN_PRINTF((    "Disable Startup DFE Tap2 Adaptation          = %d\n"  , dsd.field.dfe_tap2_adaptation       ));
   1133     EFUN_PRINTF((    "Disable Startup DFE Tap3 Adaptation          = %d\n"  , dsd.field.dfe_tap3_adaptation       ));
   1134     EFUN_PRINTF((    "Disable Startup DFE Tap4 Adaptation          = %d\n"  , dsd.field.dfe_tap4_adaptation       ));
   1135     EFUN_PRINTF((    "Disable Startup DFE Tap5 Adaptation          = %d\n"  , dsd.field.dfe_tap5_adaptation       ));
   1136     EFUN_PRINTF((    "Disable Startup DFE Tap1 DCD                 = %d\n"  , dsd.field.dfe_tap1_dcd              ));
   1137     EFUN_PRINTF((    "Disable Startup DFE Tap2 DCD                 = %d\n\n", dsd.field.dfe_tap2_dcd              ));
   1138     EFUN(                                                           merlin16_get_usr_ctrl_disable_steady_state(sa__, &dss));
   1139     EFUN_PRINTF((    "Disable Steady State PF Adaptation           = %d\n"  , dss.field.pf_adaptation             ));
   1140     EFUN_PRINTF((    "Disable Steady State DC Adaptation           = %d\n"  , dss.field.dc_adaptation             ));
   1141     EFUN_PRINTF((    "Disable Steady State Slicer Offset Tuning    = %d\n"  , dss.field.slicer_offset_tuning      ));
   1142     EFUN_PRINTF((    "Disable Steady State Clk90 offset Adaptation = %d\n"  , dss.field.clk90_offset_adaptation   ));
   1143     EFUN_PRINTF((    "Disable Steady State P1 level Tuning         = %d\n"  , dss.field.p1_level_tuning           ));
   1144     EFUN_PRINTF((    "Disable Steady State Eye Adaptation          = %d\n"  , dss.field.eye_adaptation            ));
   1145     EFUN_PRINTF((    "Disable Steady State All Adaptation          = %d\n\n", dss.field.all_adaptation            ));
   1146     EFUN(                                                      merlin16_get_usr_ctrl_disable_steady_state_dfe(sa__, &dssd));
   1147     EFUN_PRINTF((    "Disable Steady State DFE Tap1 Adaptation     = %d\n"  , dssd.field.dfe_tap1_adaptation      ));
   1148     EFUN_PRINTF((    "Disable Steady State DFE Tap2 Adaptation     = %d\n"  , dssd.field.dfe_tap2_adaptation      ));
   1149     EFUN_PRINTF((    "Disable Steady State DFE Tap3 Adaptation     = %d\n"  , dssd.field.dfe_tap3_adaptation      ));
   1150     EFUN_PRINTF((    "Disable Steady State DFE Tap4 Adaptation     = %d\n"  , dssd.field.dfe_tap4_adaptation      ));
   1151     EFUN_PRINTF((    "Disable Steady State DFE Tap5 Adaptation     = %d\n"  , dssd.field.dfe_tap5_adaptation      ));
   1152     EFUN_PRINTF((    "Disable Steady State DFE Tap1 DCD            = %d\n"  , dssd.field.dfe_tap1_dcd             ));
   1153     EFUN_PRINTF((    "Disable Steady State DFE Tap2 DCD            = %d\n\n", dssd.field.dfe_tap2_dcd             ));
   1154     ESTM_PRINTF((    "Clk90 offset Adjust                          = %d\n"  , rdv_usr_ctrl_clk90_offset_adjust()  ));
   1155     ESTM_PRINTF((    "Clk90 offset Override                        = %d\n"  , rdv_usr_ctrl_clk90_offset_override()));
   1156     ESTM_PRINTF((    "Lane Event Log Level                         = %d\n"  , rdv_usr_ctrl_lane_event_log_level() ));
   1157 
   1158     return(ERR_CODE_NONE);
   1159 }
   1160 
   1161 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) {
   1162     uint8_t i,prbs_byte,prbs_multi,time_byte,time_multi;
   1163     uint16_t sts,dataword;
   1164     int16_t offset_start;
   1165     uint8_t cnt;
   1166     uint32_t errors,timer_values;
   1167     int rate,direction;
   1168     uint8_t range250;
   1169     merlin16_osr_mode_st osr_mode;
   1170     struct merlin16_uc_core_config_st core_config;
   1171 
   1172     ENULL_MEMSET(&core_config,0,sizeof(core_config));
   1173     ENULL_MEMSET(&osr_mode,0,sizeof(osr_mode));
   1174 
   1175     EFUN(merlin16_get_uc_core_config(sa__, &core_config));
   1176     EFUN(merlin16_INTERNAL_get_osr_mode(sa__, &osr_mode));
   1177 
   1178 #ifdef wr_ams_rx_rxclk_div2p5    
   1179     if((osr_mode.rx > MERLIN16_OSX4) && (osr_mode.rx != MERLIN16_OSX2P5)) {
   1180 #else
   1181     if(osr_mode.rx > MERLIN16_OSX4) {
   1182 #endif
   1183         EFUN_PRINTF(("ERROR DIAG display_ber_data: osr mode too high\n"));
   1184         return(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1185     }
   1186     rate = core_config.vco_rate_in_Mhz/(1<<osr_mode.rx);
   1187     direction = (ber_scan_mode & DIAG_BER_NEG) ? -1 : 1 ;
   1188     range250 = (ber_scan_mode & DIAG_BER_P1_NARROW) ? 0 : 1;
   1189 
   1190     EFUN_PRINTF(("\n****  SERDES BER DATA    ****\n"));
   1191     EFUN_PRINTF(("BER MODE = %x %d %d\n",ber_scan_mode,timer_control,max_error_control));
   1192     EFUN_PRINTF(("DATA RATE = %d Mhz\n",rate));
   1193     /* start UC acquisition */
   1194     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("start begin\n"));
   1195     EFUN(merlin16_start_ber_scan_test(sa__, ber_scan_mode, timer_control, max_error_control));
   1196     ESTM(offset_start = rd_uc_dsc_data());
   1197     if(ber_scan_mode & DIAG_BER_HORZ) {
   1198         EFUN_PRINTF(("STARTING OFFSET = %d : %d mUI\n",offset_start,(offset_start*1000)>>6));
   1199     } else {
   1200         EFUN_PRINTF(("STARTING OFFSET = %d : %d mV\n",offset_start,merlin16_INTERNAL_ladder_setting_to_mV(sa__, (int8_t)offset_start, range250)));
   1201     }
   1202     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("start done\n"));
   1203 
   1204 
   1205     /* This wait is VERY LONG and should be replaced with interupt or something */
   1206     if(DIAG_VERBOSE > 5) {
   1207         do {
   1208             EFUN(USR_DELAY_US(2000000));
   1209             ESTM(sts = rdv_usr_diag_status());
   1210             EFUN_PRINTF(("sts=%04x\n",sts));
   1211 
   1212         } while ((sts & 0x8000) == 0);
   1213     } else {
   1214         EFUN_PRINTF(("Waiting for measurement time approx %d seconds",timer_control+(timer_control>>1)));
   1215         EFUN(merlin16_INTERNAL_poll_diag_done(sa__, &sts,timer_control*2000));
   1216     }
   1217     if(DIAG_VERBOSE > 2) EFUN_PRINTF(("delay done\n"));
   1218 
   1219     /* Check for completion read ln.diag_status byte?*/
   1220     ESTM(sts = rdv_usr_diag_status());
   1221     if((sts & 0x8000) == 0) {
   1222         return(_error(ERR_CODE_DATA_NOTAVAIL));
   1223     }
   1224     cnt = (sts & 0x00FF)/3;
   1225     for(i=0;i < cnt;i++) {
   1226         /* Read 2 bytes of data */
   1227         EFUN(merlin16_pmd_uc_cmd(sa__, CMD_READ_DIAG_DATA_WORD, 0, 200));
   1228         ESTM(dataword = rd_uc_dsc_data());           /* LSB contains 2 -4bit nibbles */
   1229         time_byte = (uint8_t)(dataword>>8);          /* MSB is time byte */
   1230         prbs_multi = (uint8_t)dataword & 0x0F;       /* split nibbles */
   1231         time_multi = (uint8_t)dataword>>4;
   1232         /* Read 1 bytes of data */
   1233         EFUN(merlin16_pmd_uc_cmd(sa__, CMD_READ_DIAG_DATA_BYTE, 0, 200));
   1234         ESTM(prbs_byte = (uint8_t)rd_uc_dsc_data());
   1235         errors = merlin16_INTERNAL_float12_to_uint32(prbs_byte,prbs_multi); /* convert 12bits to uint32 */
   1236         timer_values = (merlin16_INTERNAL_float12_to_uint32(time_byte,time_multi)<<3);
   1237         if(DIAG_VERBOSE < 5) {
   1238             if (!(i % 4))  {
   1239                 EFUN_PRINTF(("\n"));
   1240             }
   1241             if(ber_scan_mode & DIAG_BER_HORZ) {
   1242                 EFUN_PRINTF(("%d %d %d ",direction*(((SRDS_ABS(offset_start)-i)*1000)>>6),errors,timer_values));
   1243             } else {
   1244                 EFUN_PRINTF(("%d %d %d ",direction*merlin16_INTERNAL_ladder_setting_to_mV(sa__, (int8_t)SRDS_ABS(offset_start)-i, range250),errors,timer_values));
   1245             }
   1246 
   1247         } else {
   1248             EFUN_PRINTF(("BER Errors=%d (%02x<<%d): Time=%d (%02x<<%d)\n",errors,prbs_byte,prbs_multi,timer_values,time_byte,time_multi<<3));
   1249         }
   1250         /*if(timer_values == 0 && errors == 0) break;*/
   1251     }
   1252     EFUN_PRINTF(("\n"));
   1253     EFUN(merlin16_pmd_uc_cmd(sa__, CMD_CAPTURE_BER_END,0x00,2000));
   1254 
   1255   return(ERR_CODE_NONE);
   1256 }
   1257 
   1258 /*******************************************/
   1259 /*  Diagnostic Functions Required for SDK  */
   1260 /*******************************************/
   1261 
   1262 /* Required Diagnostic Functions */
   1263 err_code_t merlin16_display_diag_data(srds_access_t *sa__, uint16_t  diag_level) {
   1264     uint8_t rx_lock, micro_stop;
   1265     uint32_t api_version;
   1266 
   1267     EFUN_PRINTF(("\n**** SERDES DISPLAY DIAG DATA ****\n"));
   1268     ESTM_PRINTF(("Rev ID Letter  = %02X\n", rdc_revid_rev_letter()));
   1269     ESTM_PRINTF(("Rev ID Process = %02X\n", rdc_revid_process()));
   1270     ESTM_PRINTF(("Rev ID Model   = %02X\n", rdc_revid_model()));
   1271     ESTM_PRINTF(("Rev ID Model   = %02X\n", rdc_revid2()));
   1272     ESTM_PRINTF(("Rev ID # Lanes = %d\n"  ,rdc_revid_multiplicity()));
   1273     ESTM_PRINTF(("Core = %d; LANE = %d\n",merlin16_get_core(sa__),merlin16_get_lane(sa__)));
   1274     EFUN(merlin16_version(&api_version));
   1275     EFUN_PRINTF(("SERDES API Version         = %06X\n",api_version));
   1276     ESTM_PRINTF(("Common Ucode Version       = %04X", rdcv_common_ucode_version()));
   1277     ESTM_PRINTF(("_%02X\n", rdcv_common_ucode_minor_version()));
   1278     ESTM_PRINTF(("AFE Hardware Version       = 0x%X\n\n", rdcv_afe_hardware_version()));
   1279 
   1280     /* stop micro so all accesses are consistent */
   1281     ESTM(rx_lock = rd_pmd_rx_lock());
   1282     {
   1283         err_code_t err_code=ERR_CODE_NONE;
   1284         micro_stop = merlin16_INTERNAL_stop_micro(sa__,rx_lock,&err_code);
   1285         if(err_code) USR_PRINTF(("Unable to stop microcontroller,  following data is suspect\n"));
   1286     }
   1287 
   1288     EFUN(merlin16_display_lane_state_hdr());
   1289     EFUN(merlin16_display_lane_state(sa__));
   1290 
   1291 
   1292     if(diag_level & SRDS_DIAG_CORE) {
   1293         EFUN(merlin16_display_core_state_hdr());
   1294         EFUN(merlin16_display_core_state_line(sa__));
   1295     }
   1296     if(diag_level & SRDS_DIAG_EVENT_SAFE) {
   1297         merlin16_INTERNAL_event_log_dump_state_t state;
   1298         uint8_t micro_num = 0;
   1299         {
   1300             state.index = 0;
   1301             state.line_start_index = 0;
   1302             EFUN(merlin16_INTERNAL_read_event_log_with_callback(sa__, micro_num, 1, &state, merlin16_INTERNAL_event_log_dump_callback));
   1303             EFUN(merlin16_INTERNAL_event_log_dump_callback(&state, 0, 0));
   1304         }
   1305     }
   1306     if(diag_level & SRDS_DIAG_EVENT) {
   1307         EFUN(merlin16_read_event_log(sa__));
   1308     }
   1309     if(diag_level & SRDS_DIAG_EYE) {
   1310         EFUN(merlin16_display_eye_scan(sa__));
   1311     }
   1312     /* currently REG_CORE and REG_LANE dump same data. */
   1313     if((diag_level & SRDS_DIAG_REG_CORE)
   1314        || (diag_level & SRDS_DIAG_REG_LANE)) {
   1315         EFUN(merlin16_reg_dump(sa__));
   1316     }
   1317     if(diag_level & SRDS_DIAG_UC_CORE) {
   1318         EFUN(merlin16_uc_core_var_dump(sa__));
   1319     }
   1320     if(diag_level & SRDS_DIAG_UC_LANE) {
   1321         EFUN(merlin16_uc_lane_var_dump(sa__));
   1322     }
   1323     if(diag_level & SRDS_DIAG_LANE_DEBUG) {
   1324         EFUN(merlin16_display_lane_debug_status(sa__));
   1325     }
   1326     if(diag_level & SRDS_DIAG_BER_VERT) {
   1327         /* display ber projections for all channels */
   1328         uint8_t ber_mode = DIAG_BER_VERT | DIAG_BER_POS;
   1329         uint8_t timer_control = 23;       /* 30 seconds */
   1330         uint8_t err_threshold = 100 / 16; /* 100 errors */ 
   1331         EFUN(_display_ber_scan_data(sa__, ber_mode, timer_control,  err_threshold));
   1332         ber_mode = DIAG_BER_VERT | DIAG_BER_NEG;
   1333         EFUN(_display_ber_scan_data(sa__, ber_mode, timer_control,  err_threshold));
   1334     }
   1335     if(diag_level & SRDS_DIAG_BER_HORZ) {
   1336         /* display ber projections for all channels */
   1337         uint8_t ber_mode = DIAG_BER_HORZ | DIAG_BER_POS;
   1338         uint8_t timer_control = 23;       /* 30 seconds */
   1339         uint8_t err_threshold = 100 / 16; /* 100 errors */ 
   1340         EFUN(_display_ber_scan_data(sa__, ber_mode, timer_control,  err_threshold));
   1341         ber_mode = DIAG_BER_HORZ | DIAG_BER_NEG;
   1342         EFUN(_display_ber_scan_data(sa__, ber_mode, timer_control,  err_threshold));
   1343     }
   1344     
   1345     /* re enable micro */
   1346     if (!micro_stop) {
   1347         EFUN(merlin16_stop_rx_adaptation(sa__, 0));
   1348     } 
   1349 
   1350     EFUN_PRINTF(("\n\n"));
   1351     return (ERR_CODE_NONE);
   1352 
   1353 }
   1354 
   1355 typedef struct {
   1356     uint16_t addr;
   1357     uint8_t  line_byte_counter;
   1358 } merlin16_diag_access_callback_state_t;
   1359 
   1360 static err_code_t merlin16_diag_access_read_byte_callback(void *arg, uint8_t byte_count, uint16_t data) {
   1361     merlin16_diag_access_callback_state_t * const state_ptr = (merlin16_diag_access_callback_state_t *)arg;
   1362     while (byte_count > 0) {
   1363         if (state_ptr->line_byte_counter == 0) {
   1364             USR_PRINTF(("\n%04x  ", state_ptr->addr));
   1365         }
   1366         USR_PRINTF(("%02x ", data & 0xFF));
   1367         ++state_ptr->addr;
   1368         state_ptr->line_byte_counter = (state_ptr->line_byte_counter+1) % 16;
   1369         data >>= 8;
   1370         --byte_count;
   1371     }
   1372     return (ERR_CODE_NONE);
   1373 }
   1374 
   1375 static err_code_t merlin16_diag_access_read_word_callback(void *arg, uint8_t byte_count, uint16_t data) {
   1376     merlin16_diag_access_callback_state_t * const state_ptr = (merlin16_diag_access_callback_state_t *)arg;
   1377     if (state_ptr->line_byte_counter == 0) {
   1378         USR_PRINTF(("\n%04x  ", state_ptr->addr));
   1379     }
   1380     USR_PRINTF(("%04x ", data));
   1381     state_ptr->addr += 2;
   1382     state_ptr->line_byte_counter = (state_ptr->line_byte_counter+2) % 16;
   1383     return (ERR_CODE_NONE);
   1384 }
   1385 
   1386 /* Required Diagnostic Functions */
   1387 err_code_t merlin16_diag_access(srds_access_t *sa__, enum srds_diag_access_enum type, uint16_t addr, uint16_t data, uint16_t param) {
   1388     merlin16_info_t * const merlin16_info_ptr = merlin16_INTERNAL_get_merlin16_info_ptr();
   1389     merlin16_diag_access_callback_state_t state;
   1390 
   1391     EFUN(merlin16_INTERNAL_verify_merlin16_info(merlin16_info_ptr, sa__));
   1392     state.addr = addr;
   1393     state.line_byte_counter = 0;
   1394     
   1395 
   1396     switch(type) {
   1397     case SRDS_REG_READ:      {
   1398                              uint16_t tmp = 0;
   1399                              if(data > 1) {
   1400                                  uint16_t i;
   1401                                  EFUN_PRINTF(("\n****  SERDES BLK REGISTER READ    ****"));
   1402                                  for (i = 0; i < data; i++) {
   1403                                      if (!(i % 16))  {
   1404                                          ESTM_PRINTF(("\n%04x ",i+addr));
   1405                                      }
   1406                                      EFUN(merlin16_pmd_rdt_reg(sa__, i+addr,&tmp));
   1407                                      ESTM_PRINTF(("%04x ", tmp));
   1408                                  }
   1409                                  EFUN_PRINTF(("\n"));
   1410                              } else {
   1411                                  EFUN(merlin16_pmd_rdt_reg(sa__, addr,&tmp));
   1412                                  EFUN_PRINTF(("Register Read: x%04x = x%04x\n",addr,tmp));
   1413                              }
   1414                              } break;
   1415     case SRDS_REG_RMW:       {
   1416                              uint16_t tmp = 0, tmp2;
   1417                              EFUN(merlin16_pmd_rdt_reg(sa__, addr,&tmp));
   1418                              tmp2 = (tmp & ~param) | (param & data);
   1419                              EFUN(merlin16_pmd_wr_reg(sa__, addr,tmp2));
   1420                              EFUN_PRINTF(("Register RMW: x%04x = x%04x -> x%04x\n",addr,tmp,tmp2));
   1421                              } break;
   1422     case SRDS_CORE_RAM_READ_BYTE: {
   1423                              if(data > 1) {
   1424                                  EFUN_PRINTF(("\n****  SERDES BLK CORE RAM READ BYTE   ****"));
   1425                                  EFUN(merlin16_INTERNAL_rdblk_uc_generic_ram(sa__,
   1426                                                                            addr + merlin16_info_ptr->core_var_ram_base,
   1427                                                                            data,
   1428                                                                            0,
   1429                                                                            data,
   1430                                                                            &state,
   1431                                                                            merlin16_diag_access_read_byte_callback));
   1432                                  EFUN_PRINTF(("\n"));
   1433                              } else {
   1434                                  ESTM_PRINTF(("Core RAM Read byte: x%04x = x%02x\n",(uint8_t)addr,merlin16_rdbc_uc_var(sa__, __ERR, (uint8_t)addr)));
   1435                              }
   1436                              } break;
   1437     case SRDS_LANE_RAM_READ_BYTE: {
   1438                              if(data > 1) {
   1439                                  EFUN_PRINTF(("\n****  SERDES BLK LANE RAM READ BYTE   ****"));
   1440                                  EFUN(merlin16_INTERNAL_rdblk_uc_generic_ram(sa__, (addr + merlin16_info_ptr->lane_var_ram_base + (merlin16_get_physical_lane(sa__) * merlin16_info_ptr->lane_var_ram_size)),
   1441                                                                            data,
   1442                                                                            0,
   1443                                                                            data,
   1444                                                                            &state,
   1445                                                                            merlin16_diag_access_read_byte_callback));
   1446                                  EFUN_PRINTF(("\n"));
   1447                              } else {
   1448                                  ESTM_PRINTF(("Lane RAM Read byte: x%04x = x%02x\n",addr,merlin16_rdbl_uc_var(sa__, __ERR,addr)));
   1449                              }
   1450                              } break;
   1451     case SRDS_CORE_RAM_READ_WORD: {
   1452                              if(data > 1) {
   1453                                  EFUN_PRINTF(("\n****  SERDES BLK CORE RAM READ WORD   ****"));
   1454                                  EFUN(merlin16_INTERNAL_rdblk_uc_generic_ram(sa__,
   1455                                                                            addr + merlin16_info_ptr->core_var_ram_base,
   1456                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1457                                                                            0,
   1458                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1459                                                                            &state,
   1460                                                                            merlin16_diag_access_read_word_callback));
   1461                                  EFUN_PRINTF(("\n"));
   1462                              } else {
   1463                                  ESTM_PRINTF(("Core RAM Read word: x%04x = x%04x\n",addr,merlin16_rdwc_uc_var(sa__, __ERR, (uint8_t)addr)));
   1464                              }
   1465                              } break;
   1466     case SRDS_LANE_RAM_READ_WORD: {
   1467                              if(data > 1) {
   1468                                  EFUN_PRINTF(("\n****  SERDES BLK LANE RAM READ WORD   ****"));
   1469                                  EFUN(merlin16_INTERNAL_rdblk_uc_generic_ram(sa__, (addr + merlin16_info_ptr->lane_var_ram_base + (merlin16_get_physical_lane(sa__) * merlin16_info_ptr->lane_var_ram_size)),
   1470                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1471                                                                            0,
   1472                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1473                                                                            &state,
   1474                                                                            merlin16_diag_access_read_word_callback));
   1475                                  EFUN_PRINTF(("\n"));
   1476                              } else {
   1477                                  ESTM_PRINTF(("Lane RAM Read word: x%04x = x%04x\n",addr,merlin16_rdwl_uc_var(sa__, __ERR, addr)));
   1478                              }
   1479                              } break;
   1480     case SRDS_CORE_RAM_RMW_BYTE:  {
   1481                              uint8_t tmp, tmp2;
   1482                              ESTM(tmp = merlin16_rdbc_uc_var(sa__, __ERR, (uint8_t)addr));
   1483                              tmp2 = (tmp & (uint8_t)~param) | ((uint8_t)param & data);
   1484                              EFUN(merlin16_wrbc_uc_var(sa__, (uint8_t)addr,tmp2));
   1485                              EFUN_PRINTF(("Core RAM RMW byte: x%04x = x%02x -> x%02x\n",addr,tmp,tmp2));
   1486                              } break;
   1487     case SRDS_LANE_RAM_RMW_BYTE:  {
   1488                              uint8_t tmp, tmp2;
   1489                              ESTM(tmp = merlin16_rdbl_uc_var(sa__, __ERR,addr));
   1490                              tmp2 = (tmp & (uint8_t)~param) | ((uint8_t)param & data);
   1491                              EFUN(merlin16_wrbl_uc_var(sa__, addr,tmp2));
   1492                              EFUN_PRINTF(("Lane RAM RMW byte: x%04x = x%02x -> x%02x\n",addr,tmp,tmp2));
   1493                              } break;
   1494     case SRDS_CORE_RAM_RMW_WORD:  {
   1495                              uint16_t tmp, tmp2;
   1496                              ESTM(tmp = merlin16_rdwc_uc_var(sa__, __ERR, (uint8_t)addr));
   1497                              tmp2 = (tmp & ~param) | (param & data);
   1498                              EFUN(merlin16_wrwc_uc_var(sa__, (uint8_t)addr,tmp2));
   1499                              EFUN_PRINTF(("Core RAM RMW word: x%04x = x%04x -> x%04x\n",addr,tmp,tmp2));
   1500                              } break;
   1501     case SRDS_LANE_RAM_RMW_WORD:  {
   1502                              uint16_t tmp, tmp2;
   1503                              ESTM(tmp = merlin16_rdwl_uc_var(sa__, __ERR,addr));
   1504                              tmp2 = (tmp & ~param) | (param & data);
   1505                              EFUN(merlin16_wrwl_uc_var(sa__, addr,tmp2));
   1506                              EFUN_PRINTF(("Lane RAM RMW word: x%04x = x%04x -> x%04x\n",addr,tmp,tmp2));
   1507                              } break;
   1508     case SRDS_GLOB_RAM_READ_BYTE: {
   1509                              if(data > 1) {
   1510                                  EFUN_PRINTF(("\n****  SERDES BLK GLOB RAM READ BYTE   ****"));
   1511                                  EFUN(merlin16_INTERNAL_rdblk_uc_generic_ram(sa__,
   1512                                                                            0x20000000 | (uint32_t)addr,
   1513                                                                            data,
   1514                                                                            0,
   1515                                                                            data,
   1516                                                                            &state,
   1517                                                                            merlin16_diag_access_read_byte_callback));
   1518                                  EFUN_PRINTF(("\n"));
   1519                              } else {
   1520                                  ESTM_PRINTF(("Glob RAM Read byte: x%04x = x%02x\n",addr,merlin16_INTERNAL_rdb_uc_var(sa__, __ERR,addr)));
   1521                              }
   1522                              } break;
   1523     case SRDS_GLOB_RAM_RMW_BYTE:  {
   1524                              uint8_t tmp, tmp2;
   1525                              ESTM(tmp = merlin16_INTERNAL_rdb_uc_var(sa__, __ERR,addr));
   1526                              tmp2 = (tmp & (uint8_t)~param) | ((uint8_t)param & data);
   1527                              EFUN(merlin16_INTERNAL_wrb_uc_var(sa__, addr,tmp2));
   1528                              EFUN_PRINTF(("Glob RAM RMW byte: x%04x = x%02x -> x%02x\n",addr,tmp,tmp2));
   1529                              } break;
   1530     case SRDS_GLOB_RAM_READ_WORD: {
   1531                              if(data > 1) {
   1532                                  EFUN_PRINTF(("\n****  SERDES BLK GLOB RAM READ WORD   ****"));
   1533                                  EFUN(merlin16_INTERNAL_rdblk_uc_generic_ram(sa__,
   1534                                                                            0x20000000 | (uint32_t)addr,
   1535                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1536                                                                            0,
   1537                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1538                                                                            &state,
   1539                                                                            merlin16_diag_access_read_word_callback));
   1540                                  EFUN_PRINTF(("\n"));
   1541                              } else {
   1542                                  ESTM_PRINTF(("Glob RAM Read word: x%04x = x%04x\n",addr,merlin16_INTERNAL_rdw_uc_var(sa__, __ERR,addr)));
   1543                              }
   1544                              } break;
   1545     case SRDS_GLOB_RAM_RMW_WORD:  {
   1546                              uint16_t tmp, tmp2;
   1547                              ESTM(tmp = merlin16_INTERNAL_rdw_uc_var(sa__, __ERR,addr));
   1548                              tmp2 = (tmp & ~param) | (param & data);
   1549                              EFUN(merlin16_INTERNAL_wrw_uc_var(sa__, addr,tmp2));
   1550                              EFUN_PRINTF(("Glob RAM RMW word: x%04x = x%04x -> x%04x\n",addr,tmp,tmp2));
   1551                              } break;
   1552     case SRDS_UC_CMD:        {
   1553                              uint16_t tmp;
   1554                              EFUN(merlin16_pmd_uc_cmd_with_data(sa__, (enum srds_pmd_uc_cmd_enum)addr, (uint8_t)param, data, GRACEFUL_STOP_TIME));
   1555                              ESTM(tmp = rd_uc_dsc_data());
   1556                              EFUN_PRINTF(("uC Command: cmd=x%02x supp=x%02x data=x%04x returned=x%04x\n",addr,param,data,tmp));
   1557                              } break;
   1558     case SRDS_PROG_RAM_READ_BYTE: {
   1559                              if(data > 1) {
   1560                                  EFUN_PRINTF(("\n****  SERDES BLK PROG RAM READ BYTE   ****"));
   1561                                  EFUN(merlin16_INTERNAL_rdblk_uc_generic_ram(sa__,
   1562                                                                            addr,
   1563                                                                            data,
   1564                                                                            0,
   1565                                                                            data,
   1566                                                                            &state,
   1567                                                                            merlin16_diag_access_read_byte_callback));
   1568                                  EFUN_PRINTF(("\n"));
   1569                              } else {
   1570                                  ESTM_PRINTF(("Prog RAM Read byte: x%04x = x%02x\n",addr,merlin16_INTERNAL_rdb_uc_var(sa__, __ERR,addr)));
   1571                              }
   1572                              } break;
   1573     case SRDS_PROG_RAM_READ_WORD: {
   1574                              if(data > 1) {
   1575                                  EFUN_PRINTF(("\n****  SERDES BLK PROG RAM READ WORD   ****"));
   1576                                  EFUN(merlin16_INTERNAL_rdblk_uc_generic_ram(sa__,
   1577                                                                            addr,
   1578                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1579                                                                            0,
   1580                                                                            ((data+1)>>1)<<1, /* Round up to nearest word count */
   1581                                                                            &state,
   1582                                                                            merlin16_diag_access_read_word_callback));
   1583                                  EFUN_PRINTF(("\n"));
   1584                              } else {
   1585                                  ESTM_PRINTF(("Prog RAM Read word: x%04x = x%04x\n",addr,merlin16_INTERNAL_rdw_uc_var(sa__, __ERR,addr)));
   1586                              }
   1587                              } break;
   1588     case SRDS_BER_PROJ_DATA: {
   1589                              /* display ber projections for all channels */
   1590                              EFUN(_display_ber_scan_data(sa__, (uint8_t)addr, (uint8_t)data,  (uint8_t)(param>>4)));
   1591                              } break;
   1592     case SRDS_EN_BREAKPOINT: 
   1593     case SRDS_GOTO_BREAKPOINT:
   1594     case SRDS_RD_BREAKPOINT:
   1595     case SRDS_DIS_BREAKPOINT:
   1596     default: EFUN_PRINTF(("Invalid request type merlin16_diag_access\n"));
   1597     }
   1598 
   1599     return(ERR_CODE_NONE);
   1600 }
   1601 
   1602 err_code_t merlin16_display_state (srds_access_t *sa__) {
   1603     EFUN(merlin16_display_core_state(sa__));
   1604     EFUN(merlin16_display_lane_state_hdr());
   1605     EFUN(merlin16_display_lane_state(sa__));
   1606     EFUN(merlin16_display_lane_state_legend());
   1607     return(ERR_CODE_NONE);
   1608 }
   1609 
   1610 err_code_t merlin16_display_config (srds_access_t *sa__) {
   1611     EFUN(merlin16_display_core_config(sa__));
   1612     EFUN(merlin16_display_lane_config(sa__));
   1613     return(ERR_CODE_NONE);
   1614 }
   1615 
   1616 /*************************/
   1617 /*  Temperature forcing  */
   1618 /*************************/
   1619 
   1620 err_code_t merlin16_force_die_temperature (srds_access_t *sa__, int16_t die_temp) {
   1621     /* disable force */ 
   1622     if(die_temp == -255) {
   1623         EFUN(wrc_micro_pvt_tempdata_frc(0));
   1624         return(ERR_CODE_NONE);
   1625     }
   1626 
   1627     /* enable force */
   1628     if (die_temp>130)
   1629         die_temp = 130;
   1630     if (die_temp<-45)
   1631         die_temp = -45;
   1632 
   1633     EFUN(wrc_micro_pvt_tempdata_frcval(_degC_to_bin(die_temp)));
   1634     EFUN(wrc_micro_pvt_tempdata_frc(1));
   1635 
   1636     return(ERR_CODE_NONE);
   1637 }
   1638 
   1639 /**********************/
   1640 /*  CL72/CL93 Status  */
   1641 /**********************/
   1642 
   1643 
   1644 err_code_t merlin16_display_cl72_status(srds_access_t *sa__) {
   1645   EFUN_PRINTF(("\n\n************************\n"                                                                                                                              ));
   1646   ESTM_PRINTF((   "** LANE %d CL72 Status **\n"                                                                                        , merlin16_get_lane(sa__)               ));
   1647   EFUN_PRINTF((    "************************\n"                                                                                                                              ));
   1648   ESTM_PRINTF((    "cl72_signal_detect         = %d   (1 = CL72 training FSM in SEND_DATA state;  0 = CL72 in training state)\n"       , rd_cl72_training_fsm_signal_detect()));
   1649   ESTM_PRINTF((    "cl72_ieee_training_failure = %d   (1 = Training failure detected;             0 = Training failure not detected)\n", rd_cl72_ieee_training_failure()     ));
   1650   ESTM_PRINTF((    "cl72_ieee_training_status  = %d   (1 = Start-up protocol in progress;         0 = Start-up protocol complete)\n"   , rd_cl72_ieee_training_status()      ));
   1651   ESTM_PRINTF((    "cl72_ieee_receiver_status  = %d   (1 = Receiver trained and ready to receive; 0 = Receiver training)\n\n"          , rd_cl72_ieee_receiver_status()      ));
   1652   return(ERR_CODE_NONE);
   1653 }
   1654 
   1655 
   1656 
   1657