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_pcieg3_diag.c (70841B)


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