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

falcon_tsc_functions.c (102628B)


      1 /***********************************************************************************
      2 ***********************************************************************************
      3 *  File Name     :  falcon_tsc_functions.c                                        *
      4 *  Created On    :  29/04/2013                                                    *
      5 *  Created By    :  Kiran Divakar                                                 *
      6 *  Description   :  APIs for Serdes IPs                                           *
      7 *                                                                                 *
      8 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      9 * 
     10 * Copyright 2007-2019 Broadcom Inc. All rights reserved.                                                           *
     11 *  No portions of this material may be reproduced in any form without             *
     12 *  the written permission of:                                                     *
     13 *      Broadcom Corporation                                                       *
     14 *      5300 California Avenue                                                     *
     15 *      Irvine, CA  92617                                                          *
     16 *                                                                                 *
     17 *  All information contained in this document is Broadcom Corporation             *
     18 *  company private proprietary, and trade secret.                                 *
     19  */
     20 
     21 /** @file falcon_tsc_functions.c
     22  * Implementation of API functions
     23  */
     24 
     25 #ifdef _MSC_VER
     26 /* Enclose all standard headers in a pragma to remove warings for MS compiler */
     27 #pragma warning( push, 0 )
     28 #endif
     29 
     30 #ifdef SERDES_API_FLOATING_POINT
     31 #include <math.h>
     32 #endif
     33 #ifdef _MSC_VER
     34 #pragma warning( pop )
     35 #endif
     36 
     37 #include <phymod/phymod_system.h>
     38 #include "falcon_tsc_functions.h"
     39 #include "falcon_tsc_field_access_c.h"
     40 #include "falcon_tsc_internal_c.h"
     41 #include "falcon_tsc_dv_functions_c.h"
     42 
     43 
     44 
     45 #include "falcon_tsc_pll_config_c.h"
     46 
     47 
     48 
     49 
     50 
     51 /************************************/
     52 /*  Display Eye Scan                */
     53 /************************************/
     54 
     55 /* This is best method for terminal ASCII display */
     56 err_code_t falcon_tsc_display_eye_scan (const phymod_access_t *pa){
     57 	uint32_t stripe[64];
     58 	uint16_t status = 0;
     59 	int8_t y;
     60 
     61 	EFUN(falcon_tsc_display_eye_scan_header (pa, 1));
     62 	/* start horizontal acquisition */
     63 	{   err_code_t err_code = falcon_tsc_meas_eye_scan_start (pa, EYE_SCAN_HORIZ);
     64 	    if (err_code)
     65 		    EFUN((falcon_tsc_meas_eye_scan_done (pa ), err_code)); }
     66 
     67 	/* display stripes */
     68 	for (y = 62; y >= -62; y = y - 2) {
     69 		{   err_code_t err_code = falcon_tsc_read_eye_scan_stripe (pa, &stripe[0], &status);
     70 		    if (err_code)
     71 			    EFUN((falcon_tsc_meas_eye_scan_done (pa ), err_code)); }
     72 		EFUN(falcon_tsc_display_eye_scan_stripe (pa, y, &stripe[0]));
     73 		EFUN_PRINTF(("\n"));
     74 	}
     75 	/* stop acquisition */
     76 	EFUN(falcon_tsc_meas_eye_scan_done (pa ));
     77 	EFUN(falcon_tsc_display_eye_scan_footer (pa, 1));
     78 
     79 	return ERR_CODE_NONE;
     80 }
     81 
     82 /* This function is for Falcon and is configured for passive mode */
     83 err_code_t falcon_tsc_meas_lowber_eye (const phymod_access_t *pa, const struct falcon_tsc_eyescan_options_st eyescan_options, uint32_t *buffer){
     84 	int8_t y, x;
     85 	int16_t i;
     86 	uint16_t status;
     87 	uint32_t errors = 0;
     88 	uint16_t timeout;
     89         uint8_t timeout_control;
     90 	uint8_t stopped_state;
     91 
     92 	if (!buffer)
     93 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
     94 	i = 0;
     95 	ESTM(stopped_state = rdv_usr_sts_micro_stopped());
     96 
     97 	timeout = eyescan_options.timeout_in_milliseconds;
     98         if (timeout > 255){
     99             timeout_control = 255;
    100         }else{
    101             timeout_control = (uint8_t)timeout;
    102         }
    103 	EFUN(wrcv_diag_max_time_control(timeout_control));
    104 
    105 	EFUN(wrv_usr_diag_mode(eyescan_options.mode));
    106 
    107 	EFUN_PRINTF(("Calculating\n"));
    108 	for (y = eyescan_options.vert_max; y >= eyescan_options.vert_min; y = y - eyescan_options.vstep) {
    109 		for (x = eyescan_options.horz_min; x <= eyescan_options.horz_max; x = x + eyescan_options.hstep) {
    110 			/* acquire sample */
    111 			EFUN(falcon_tsc_pmd_uc_cmd_with_data (pa, CMD_DIAG_EN, CMD_UC_DIAG_GET_EYE_SAMPLE, ((uint16_t)x) << 8 | (uint8_t)y, 200));
    112 			/* wait for sample complete */
    113 #if 0
    114 			do {
    115 				EFUN(falcon_tsc_delay_us(1000));
    116 				ESTM(status = rdv_usr_diag_status());
    117 				EFUN_PRINTF(("status=%04x\n", status));
    118 			} while ((status & 0x8000) == 0);
    119 #else
    120 			EFUN(falcon_tsc_poll_diag_done (pa, &status, (((uint32_t)timeout) << 7) * 10 + 20000));
    121 #endif
    122 			EFUN(falcon_tsc_prbs_err_count_ll (pa, &errors));
    123 			/* EFUN_PRINTF(("(%d,%d) = %u\n",x,y,errors & 0x7FFFFFF));    */
    124 
    125 			buffer[i] = errors & 0x7FFFFFFF;
    126 
    127 			i++;
    128 			EFUN_PRINTF(("."));
    129 		}
    130 		EFUN_PRINTF(("\n"));
    131 	}
    132 	EFUN_PRINTF(("\n"));
    133 	EFUN(falcon_tsc_meas_eye_scan_done (pa ));
    134 	EFUN(wrv_usr_sts_micro_stopped(stopped_state));
    135 	return ERR_CODE_NONE;
    136 }
    137 
    138 
    139 /* Display the LOW BER EyeScan */
    140 err_code_t falcon_tsc_display_lowber_eye (const phymod_access_t *pa, const struct falcon_tsc_eyescan_options_st eyescan_options, uint32_t *buffer){
    141 	int8_t x, y, i, z;
    142 	int16_t j; /* buffer pointer */
    143 	uint32_t val;
    144 	uint8_t overflow;
    145 	uint32_t limits[13]; /* allows upto 400 sec test time per point (1e-13 BER @ 10G) */
    146 
    147 	if (!buffer)
    148 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
    149 
    150 	/* Calculate initial total bitcount BER 1e-1 */
    151 	limits[0] = _mult_with_overflow_check (pa, eyescan_options.linerate_in_khz / 10, eyescan_options.timeout_in_milliseconds, &overflow);
    152 	if (overflow > 0) {
    153 		limits[0] = UINT32_MAX;
    154 		EFUN_PRINTF(("Very long timout_in_milliseconds results in saturation of Err counter can cause in accurate results\n"));
    155 	}
    156 
    157 	for (i = 1; i < 13; i++)   /* calculate thresholds */
    158 		limits[i] = limits[i - 1] / 10;
    159 
    160 	EFUN(falcon_tsc_display_eye_scan_header (pa, 1));
    161 	j = 0;
    162 	for (y = eyescan_options.vert_max; y >= eyescan_options.vert_min; y = y - eyescan_options.vstep) {
    163 		ESTM_PRINTF(("%6dmV : ", _ladder_setting_to_mV (pa, y, 0                 )));
    164 		for (z = -31; z < eyescan_options.horz_min; z++)
    165 			EFUN_PRINTF((" ")); /* add leading spaces if any */
    166 		for (x = eyescan_options.horz_min; x <= eyescan_options.horz_max; x = x + eyescan_options.hstep) {
    167 /*        val = float8_to_int32(buffer[j); */
    168 			val = buffer[j];
    169 
    170 			for (i = 0; i < 13; i++) {
    171 				if ((val != 0) & ((val >= limits[i]) | (limits[i] == 0))) {
    172 					for (z = 1; z <= eyescan_options.hstep; z++) {
    173 						if (z == 1) {
    174 							if (i <= 8)
    175 								EFUN_PRINTF(("%c", '1' + i));
    176 							else
    177 								EFUN_PRINTF(("%c", 'A' + i - 9));
    178 						} else
    179 							EFUN_PRINTF((" "));
    180 					}
    181 					break;
    182 				}
    183 			}
    184 			if (i == 13) {
    185 				for (z = 1; z <= eyescan_options.hstep; z++) {
    186 					if (z == 1) {
    187 						if ((x % 5) == 0 && (y % 5) == 0)
    188 							EFUN_PRINTF(("+"));
    189 						else if ((x % 5) != 0 && (y % 5) == 0)
    190 							EFUN_PRINTF(("-"));
    191 						else if ((x % 5) == 0 && (y % 5) != 0)
    192 							EFUN_PRINTF((":"));
    193 						else
    194 							EFUN_PRINTF((" "));
    195 					} else
    196 						EFUN_PRINTF((" "));
    197 				}
    198 			}
    199 			j++;
    200 		}
    201 		EFUN_PRINTF(("\n"));
    202 	}
    203 	EFUN(falcon_tsc_display_eye_scan_footer (pa, 1));
    204 	return ERR_CODE_NONE;
    205 }
    206 
    207 err_code_t falcon_tsc_meas_eye_scan_start (const phymod_access_t *pa, uint8_t direction){
    208 	uint8_t lock;
    209 
    210 	ESTM(lock = rd_pmd_rx_lock());
    211 	if (lock == 0) {
    212 		EFUN_PRINTF(("Error: No PMD_RX_LOCK on lane requesting 2D eye scan\n"));
    213 		return ERR_CODE_DIAG_SCAN_NOT_COMPLETE;
    214 	}
    215 	if (direction == EYE_SCAN_VERTICAL)
    216 		EFUN(falcon_tsc_pmd_uc_diag_cmd (pa, CMD_UC_DIAG_START_VSCAN_EYE, 200));
    217 	else
    218 		EFUN(falcon_tsc_pmd_uc_diag_cmd (pa, CMD_UC_DIAG_START_HSCAN_EYE, 200));
    219 	return ERR_CODE_NONE;
    220 }
    221 
    222 err_code_t falcon_tsc_read_eye_scan_stripe (const phymod_access_t *pa, uint32_t *buffer, uint16_t *status){
    223 	uint32_t val[2] = { 0, 0 };
    224 	uint16_t sts = 0;
    225 	int8_t i;
    226 
    227 	if (!buffer || !status)
    228 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
    229 	*status = 0;
    230 	for (i = 0; i < 32; i++) {
    231 		{   err_code_t err_code = falcon_tsc_poll_diag_eye_data (pa, &val[0], &sts, 200);
    232 		    *status |= sts & 0xF000;
    233 		    if (err_code)
    234 			    return err_code; }
    235 		buffer[i * 2]     = val[0];
    236 		buffer[(i * 2) + 1] = val[1];
    237 	}
    238 	*status |= sts & 0x00FF;
    239 	return ERR_CODE_NONE;
    240 }
    241 
    242 err_code_t falcon_tsc_display_eye_scan_stripe (const phymod_access_t *pa, int8_t y, uint32_t *buffer){
    243 
    244 	const uint32_t limits[7] = { 1835008, 183501, 18350, 1835, 184, 18, 2 };
    245 
    246 	int8_t x, i;
    247 	int16_t level;
    248 
    249 	/* ESTM(data_thresh = rd_rx_data_thresh_sel()); */
    250 	level = _ladder_setting_to_mV (pa, y, 0);
    251 
    252 	if (!buffer)
    253 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
    254 
    255 	EFUN_PRINTF(("%6dmV : ", level));
    256 
    257 	for (x = -31; x < 32; x++) {
    258 		for (i = 0; i < 7; i++)
    259 			if (buffer[x + 31] >= limits[i]) {
    260 				EFUN_PRINTF(("%c", '0' + i + 1));
    261 				break;
    262 			}
    263 		if (i == 7) {
    264 			if ((x % 5) == 0 && (y % 5) == 0) EFUN_PRINTF(("+")); else if ((x % 5) != 0 && (y % 5) == 0) EFUN_PRINTF(("-")); else if ((x % 5) == 0 && (y % 5) != 0) EFUN_PRINTF((":")); else EFUN_PRINTF((" "));
    265 		}
    266 	}
    267 	return ERR_CODE_NONE;
    268 }
    269 
    270 err_code_t falcon_tsc_display_eye_scan_header (const phymod_access_t *pa, int8_t i){
    271 	int8_t x;
    272 
    273 	EFUN_PRINTF(("\n"));
    274 	EFUN_PRINTF((" Each character N represents approximate error rate 1e-N at that location\n"));
    275 	for (x = 1; x <= i; x++)
    276 		EFUN_PRINTF(("  UI/64  : -30  -25  -20  -15  -10  -5    0    5    10   15   20   25   30"));
    277 	EFUN_PRINTF(("\n"));
    278 	for (x = 1; x <= i; x++)
    279 		EFUN_PRINTF(("         : -|----|----|----|----|----|----|----|----|----|----|----|----|-"));
    280 	EFUN_PRINTF(("\n"));
    281 	return ERR_CODE_NONE;
    282 }
    283 
    284 err_code_t falcon_tsc_display_eye_scan_footer (const phymod_access_t *pa, int8_t i){
    285 	int8_t x;
    286 
    287 	for (x = 1; x <= i; x++)
    288 		EFUN_PRINTF(("         : -|----|----|----|----|----|----|----|----|----|----|----|----|-"));
    289 	EFUN_PRINTF(("\n"));
    290 	for (x = 1; x <= i; x++)
    291 		EFUN_PRINTF(("  UI/64  : -30  -25  -20  -15  -10  -5    0    5    10   15   20   25   30"));
    292 	EFUN_PRINTF(("\n"));
    293 	return ERR_CODE_NONE;
    294 }
    295 
    296 
    297 /*eye_scan_status_t falcon_tsc_read_eye_scan_status (pa, void) */
    298 err_code_t falcon_tsc_read_eye_scan_status (const phymod_access_t *pa, uint16_t *status){
    299 
    300 	if (!status)
    301 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
    302 
    303 	ESTM(*status = rdv_usr_diag_status());
    304 
    305 	return ERR_CODE_NONE;
    306 }
    307 
    308 
    309 err_code_t falcon_tsc_meas_eye_scan_done (const phymod_access_t *pa){
    310 	EFUN(falcon_tsc_pmd_uc_diag_cmd (pa, CMD_UC_DIAG_DISABLE, 200));
    311 	return ERR_CODE_NONE;
    312 }
    313 
    314 
    315 err_code_t falcon_tsc_start_ber_scan_test (const phymod_access_t *pa, uint8_t ber_scan_mode, uint8_t timer_control, uint8_t max_error_control){
    316 	uint8_t lock, sts;
    317 
    318 	ESTM(lock = rd_pmd_rx_lock());
    319 	if (lock == 0) {
    320 		EFUN_PRINTF(("Error: No PMD_RX_LOCK on lane requesting BER scan\n"));
    321 		return ERR_CODE_DIAG_SCAN_NOT_COMPLETE;
    322 	}
    323 	ESTM(sts = rdv_usr_sts_micro_stopped());
    324 	if (sts > 1) {
    325 		EFUN_PRINTF(("Error: Lane is busy (%d) requesting BER scan\n", sts));
    326 		return ERR_CODE_DIAG_SCAN_NOT_COMPLETE;
    327 	}
    328 
    329 	EFUN(wrcv_diag_max_time_control(timer_control));
    330 	EFUN(wrcv_diag_max_err_control(max_error_control));
    331 	EFUN(falcon_tsc_pmd_uc_cmd (pa, CMD_CAPTURE_BER_START, ber_scan_mode, 500));
    332 	return ERR_CODE_NONE;
    333 }
    334 
    335 err_code_t falcon_tsc_read_ber_scan_data (const phymod_access_t *pa, uint32_t *errors, uint32_t *timer_values, uint8_t *cnt, uint32_t timeout){
    336 	uint8_t i, prbs_byte, prbs_multi, time_byte, time_multi;
    337 	uint16_t sts, dataword;
    338 
    339 	if (!errors || !timer_values || !cnt)
    340 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
    341 	/* init data arrays */
    342 	for (i = 0; i < DIAG_MAX_SAMPLES; i++) {
    343 		errors[i] = 0;
    344 		timer_values[i] = 0;
    345 	}
    346 	/* Check for completion read ln.diag_status byte?*/
    347 	ESTM(sts = rdv_usr_diag_status());
    348 	if ((sts & 0x8000) == 0)
    349 		return _error(ERR_CODE_DATA_NOTAVAIL);
    350 	*cnt = (sts & 0x00FF) / 3;
    351 	for (i = 0; i < *cnt; i++) {
    352 		/* Read 2 bytes of data */
    353 		EFUN(falcon_tsc_pmd_uc_cmd (pa,  CMD_READ_DIAG_DATA_WORD, 0, timeout));
    354 		ESTM(dataword = rd_uc_dsc_data());      /* LSB contains 2 -4bit nibbles */
    355 		time_byte = (uint8_t)(dataword >> 8);   /* MSB is time byte */
    356 		prbs_multi = (uint8_t)dataword & 0x0F;  /* split nibbles */
    357 		time_multi = (uint8_t)dataword >> 4;
    358 		/* Read 1 bytes of data */
    359 		EFUN(falcon_tsc_pmd_uc_cmd (pa,  CMD_READ_DIAG_DATA_BYTE, 0, timeout));
    360 		ESTM(prbs_byte = (uint8_t)rd_uc_dsc_data());
    361 		errors[i] = _float12_to_uint32 (pa, prbs_byte, prbs_multi); /* convert 12bits to uint32 */
    362 		timer_values[i] = (_float12_to_uint32 (pa, time_byte, time_multi) << 3);
    363 		/*  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)); */
    364 		/*if(timer_values[i] == 0 && errors[i] == 0) break;*/
    365 	}
    366 
    367 	return ERR_CODE_NONE;
    368 }
    369 
    370 
    371 /* This is good example function to do BER extrapolation */
    372 err_code_t falcon_tsc_eye_margin_proj (const phymod_access_t *pa, USR_DOUBLE rate, uint8_t ber_scan_mode, uint8_t timer_control, uint8_t max_error_control){
    373 	uint32_t errs[DIAG_MAX_SAMPLES];
    374 	uint32_t time[DIAG_MAX_SAMPLES];
    375 	uint8_t i, cnt;
    376 	uint16_t sts;
    377 	int16_t offset_start;
    378 	/* Below 'verbose' level is intended to be modified only within a debug */
    379 	/* session immediately after a breakpoint, and to retain its state only */
    380 	/* through function exit:  therefore it must be 'volatile' to prevent a */
    381 	/* compiler from eliding code conditioned on it, but NOT 'static'.      */
    382 	uint8_t volatile verbose = 0;
    383 
    384 
    385 	for (i = 0; i < DIAG_MAX_SAMPLES; i++) {
    386 		errs[i] = 0;
    387 		time[i] = 0;
    388 	}
    389 	/* start UC acquisition */
    390 	if (verbose > 2) EFUN_PRINTF(("start begin\n"));
    391 	EFUN(falcon_tsc_start_ber_scan_test (pa, ber_scan_mode, timer_control, max_error_control));
    392 	ESTM(offset_start = rd_uc_dsc_data());
    393 	if (verbose > 2) EFUN_PRINTF(("offset_start = %d:%dmV\n", offset_start, _ladder_setting_to_mV (pa, (int8_t)offset_start, 0)));
    394 	if (verbose > 2) EFUN_PRINTF(("start done\n"));
    395 
    396 	/* This wait is VERY LONG and should be replaced with interupt or something */
    397 	if (verbose > 5) {
    398 		do {
    399 			EFUN(falcon_tsc_delay_us(2000000));
    400 			ESTM(sts = rdv_usr_diag_status());
    401 			EFUN_PRINTF(("sts=%04x\n", sts));
    402 
    403 		} while ((sts & 0x8000) == 0);
    404 	} else {
    405 		EFUN_PRINTF(("Waiting for measurement time approx %d seconds", timer_control + (timer_control >> 1)));
    406 		EFUN(falcon_tsc_poll_diag_done (pa, &sts, timer_control * 2000));
    407 	}
    408 	if (verbose > 2) EFUN_PRINTF(("delay done\n"));
    409 
    410 	EFUN(falcon_tsc_read_ber_scan_data (pa,  &errs[0], &time[0], &cnt, 2000));
    411 
    412 	if (verbose > 2) EFUN_PRINTF(("read done cnt=%d\n", cnt));
    413 
    414 	EFUN(falcon_tsc_pmd_uc_cmd (pa, CMD_CAPTURE_BER_END, 0x00, 50));
    415 
    416 	if (verbose > 2) EFUN_PRINTF(("end function done\n"));
    417 	/* if(cnt == 1) {                                                     */
    418 	/*     EFUN_PRINTF(("Not enough points found to extrapolate BER\n")); */
    419 	/*     return(ERR_CODE_NONE);                                         */
    420 	/* }                                                                  */
    421 
    422 	EFUN(falcon_tsc_display_ber_scan_data (pa, rate, ber_scan_mode, &errs[0], &time[0], (uint8_t)_abs(offset_start)));
    423 
    424 	if (verbose > 2) EFUN_PRINTF(("display done\n"));
    425 
    426 	return ERR_CODE_NONE;
    427 }
    428 
    429 
    430 
    431 err_code_t falcon_tsc_display_ber_scan_data (const phymod_access_t *pa, USR_DOUBLE rate, uint8_t ber_scan_mode, uint32_t *total_errs, uint32_t *total_time, uint8_t max_offset){
    432 
    433 #ifdef SERDES_API_FLOATING_POINT
    434 	/* 'margins_mv[]' vector maps the p1 threshold code with actual mV
    435 	    Only relevant when mode=0
    436 	    This is not totally linear: for code 0~25 step=6mV; code 25~30 step=18mV; code 30~31 step=12
    437 	    'margins_mv[]' is valid only for Merlin. This vector would need to be modified accordingly for different Serdes
    438 	   USR_DOUBLE margins_mv[] = {0,6,12,18,24,30,36,42,48,54,60,66,72,78,84,
    439 	                       90,96,102,108,114,120,126,132,138,144,150,168,186,204,222,240,252};
    440 	   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,
    441 	                                    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}; */
    442 	const unsigned int HI_CONFIDENCE_ERR_CNT = 100;         /* bit errors */
    443 	const unsigned int HI_CONFIDENCE_MIN_ERR_CNT = 20;      /* bit errors */
    444 	const unsigned int MAX_CLIPPED_ERR_CNT = 8355840;
    445 	const USR_DOUBLE ARTIFICIAL_BER = 0.5;                  /* used along ARTIFICIAL_MARGIN(_V/_H) when not enough points to extrapolate */
    446 	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 */
    447 	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 */
    448 	const int MIN_BER_TO_REPORT = -24;                      /* we clip the projected BER using this number */
    449 	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) */
    450 	const int8_t verbose = 1;                               /* set verbosity to 1 for normal API operation */
    451 
    452 	/* BER confidence scale */
    453 	const USR_DOUBLE ber_conf_scale[104] = {
    454 		2.9957, 5.5717, 3.6123, 2.9224, 2.5604, 2.3337, 2.1765, 2.0604, 1.9704, 1.8983,
    455 		1.8391, 1.7893, 1.7468, 1.7100, 1.6778, 1.6494, 1.6239, 1.6011, 1.5804, 1.5616,
    456 		1.5444, 1.5286, 1.5140, 1.5005, 1.4879, 1.4762, 1.4652, 1.4550, 1.4453, 1.4362,
    457 		1.4276, 1.4194, 1.4117, 1.4044, 1.3974, 1.3908, 1.3844, 1.3784, 1.3726, 1.3670,
    458 		1.3617, 1.3566, 1.3517, 1.3470, 1.3425, 1.3381, 1.3339, 1.3298, 1.3259, 1.3221,
    459 		1.3184, 1.3148, 1.3114, 1.3080, 1.3048, 1.3016, 1.2986, 1.2956, 1.2927, 1.2899,
    460 		1.2872, 1.2845, 1.2820, 1.2794, 1.2770, 1.2746, 1.2722, 1.2700, 1.2677, 1.2656,
    461 		1.2634, 1.2614, 1.2593, 1.2573, 1.2554, 1.2535, 1.2516, 1.2498, 1.2481, 1.2463,
    462 		1.2446, 1.2429, 1.2413, 1.2397, 1.2381, 1.2365, 1.2350, 1.2335, 1.2320, 1.2306,
    463 		1.2292, 1.2278, 1.2264, 1.2251, 1.2238, 1.2225, 1.2212, 1.2199, 1.2187, 1.2175,
    464 		1.2163, /* starts in index: 100 for #errors: 100,200,300,400 */
    465 		1.1486, /* 200 */
    466 		1.1198, /* 300 */
    467 		1.1030
    468 	};              /*400 */
    469 
    470 
    471 	/* Define variables */
    472 	USR_DOUBLE lbers[DIAG_MAX_SAMPLES];             /* Internal linear scale sqrt(-log(ber)) */
    473 	USR_DOUBLE margins[DIAG_MAX_SAMPLES];           /* Eye margin @ each measurement */
    474 	USR_DOUBLE bers[DIAG_MAX_SAMPLES];              /* computed bit error rate */
    475 	uint32_t i;
    476 	int8_t offset[DIAG_MAX_SAMPLES];
    477 	int8_t mono_flags[DIAG_MAX_SAMPLES];
    478 
    479 	int8_t direction;
    480 	uint8_t heye;
    481 	int8_t delta_n;
    482 	USR_DOUBLE Exy = 0.0;
    483 	USR_DOUBLE Eyy = 0.0;
    484 	USR_DOUBLE Exx = 0.0;
    485 	USR_DOUBLE Ey  = 0.0;
    486 	USR_DOUBLE Ex  = 0.0;
    487 	USR_DOUBLE alpha = 0.0;
    488 	USR_DOUBLE gauss_noise = -1;
    489 	USR_DOUBLE beta = 0.0;
    490 	USR_DOUBLE sq_r = 0.0, alpha2 = 0.0;
    491 	USR_DOUBLE proj_ber = 0.0, proj_ber_aux = 0.0;
    492 	USR_DOUBLE proj_margin_12 = 0.0;
    493 	USR_DOUBLE proj_margin_15 = 0.0;
    494 	USR_DOUBLE proj_margin_18 = 0.0;
    495 	USR_DOUBLE sq_err1 = 0.0, sq_err2 = 0.0;
    496 	USR_DOUBLE ierr;
    497 	uint8_t start_n;
    498 	uint8_t stop_n;
    499 	uint8_t low_confidence;
    500 	uint8_t loop_index;
    501 	uint8_t n_mono = 0;
    502 	uint8_t eye_cnt = 1;
    503 	uint8_t hi_confidence_cnt = 0;
    504 	int8_t first_good_ber_idx = -1;
    505 	int8_t first_small_errcnt_idx = -1;
    506 	int8_t first_non_clipped_errcnt_idx = -1;
    507 	uint8_t range250;
    508 	uint8_t intrusive;
    509 	uint8_t ber_clipped = 0;
    510 	uint8_t last_point_discard;
    511 	uint8_t fit_count;
    512 	int artificial_margin;
    513 	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 */
    514 	USR_DOUBLE artificial_lber;
    515 	char message[256] = "NO MESSAGE";
    516 	char unit[5];
    517 
    518 	if (!total_errs || !total_time )
    519 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
    520 
    521 	/* Initialize BER array */
    522 	for (i = 0; i < DIAG_MAX_SAMPLES; i++) {
    523 		bers[i] = 0;
    524 		mono_flags[i] = 0;
    525 	}
    526 
    527 	/* Decode mode/direction/etc. */
    528 	heye = (ber_scan_mode & DIAG_BER_HORZ) >> 1;
    529 	direction = (ber_scan_mode & DIAG_BER_NEG) ? -1 : 1;
    530 	range250 = (ber_scan_mode & DIAG_BER_P1_NARROW) ? 0 : 1;
    531 	intrusive = (ber_scan_mode & DIAG_BER_INTR) ? 1 : 0;
    532 
    533 	/* Prepare artificial points in case they are needed */
    534 	if (heye == 1)
    535 		artificial_margin = direction * ARTIFICIAL_MARGIN_H;
    536 	else
    537 		artificial_margin = direction * ARTIFICIAL_MARGIN_V;
    538 	artificial_lber = (USR_DOUBLE)sqrt(-log10(ARTIFICIAL_BER));
    539 
    540 	/* Printing on-screen message */
    541 	if (heye == 1) {
    542 		if (verbose > 0) {
    543 			if (direction == -1) EFUN_PRINTF(("\n\n********** HORIZONTAL PROJECTION: LEFT SIDE ******************\n"));
    544 			if (direction == 1) EFUN_PRINTF(("\n\n********** HORIZONTAL PROJECTION: RIGHT SIDE *****************\n"));
    545 		}
    546 	} else {
    547 		if (verbose > 0) {
    548 			if (direction == -1) EFUN_PRINTF(("\n\n********** VERTICAL PROJECTION: BOTTOM ***********************\n"));
    549 			if (direction == 1) EFUN_PRINTF(("\n\n********** VERTICAL PROJECTION: TOP **************************\n"));
    550 		}
    551 	}
    552 
    553 	/* *******************************************
    554 	* Generate margins[]
    555 	* Generate ber[]
    556 	* Find first and last points for linear fit
    557  */
    558 	i = 0;
    559 	do {
    560 		if (heye == 1) {
    561 			ENULL_STRCPY(unit, "mUI");
    562 			offset[i] = (int8_t)(max_offset - i);
    563 #ifndef STANDALONE_EVENT
    564 			margins[i] = direction * offset[i] * 1000.0 / 64.0;
    565 #else
    566 			margins[i] = info_out->margins[i];
    567 #endif
    568 		} else {
    569 			ENULL_STRCPY(unit, "mV");
    570 			offset[i] = (int8_t)(max_offset - i);
    571 #ifndef STANDALONE_EVENT
    572 			if (intrusive)
    573 				margins[i] = direction * _ladder_setting_to_mV (pa, offset[i], 0);
    574 			else
    575 				margins[i] = direction * _ladder_setting_to_mV (pa, offset[i], range250);
    576 
    577 #else
    578 			margins[i] = info_out->margins[i];
    579 #endif
    580 		}
    581 		if (total_errs[i] == 0)
    582 			bers[i] = 1.0 / (((USR_DOUBLE)total_time[i]) * 0.00001 * rate);
    583 		else
    584 			bers[i] = (USR_DOUBLE)total_errs[i] / (((USR_DOUBLE)total_time[i]) * 0.00001 * rate);
    585 
    586 		/* Find the first data point with good BER (BER <= 10^MIN_BER_FOR_FIT)
    587 		   NOTE: no need for lower bound on BER, since correction factors will be applied for all total_errs>=0 */
    588 		if ((log10(bers[i]) <= MIN_BER_FOR_FIT) && (first_good_ber_idx == -1))
    589 			first_good_ber_idx = (int8_t)i;
    590 
    591 		/* Determine high-confidence iterations */
    592 		if (total_errs[i] >= HI_CONFIDENCE_ERR_CNT)
    593 			hi_confidence_cnt++;
    594 		else if ((total_errs[i] < HI_CONFIDENCE_MIN_ERR_CNT) && (first_small_errcnt_idx == -1))
    595 			/* find the first data point with small error count */
    596 			first_small_errcnt_idx = (int8_t)i;
    597 
    598 		/* Determine first NON-clipped error count
    599 		    NOTE: Originally this limit was created for post processing of micro-generated data; however, this could be used for PC-generated data as well */
    600 		if ((total_errs[i] < MAX_CLIPPED_ERR_CNT) && (first_non_clipped_errcnt_idx == -1) )
    601 			first_non_clipped_errcnt_idx = (int8_t)i;
    602 
    603 		i++;
    604 
    605 	} while (((total_errs[i] != 0) || (total_time[i] != 0)) && (i <= max_offset));
    606 
    607 	eye_cnt = (int8_t)i;
    608 
    609 
    610 	/* *******************************************
    611 	   Setting up stop_n variable.
    612 	   Check if:
    613 	    - There is only one point in measurement vector (i.e. eye_cnt = 1)
    614 	    - The very last point's measurement time was "too short"
    615  */
    616 
    617 	i = eye_cnt - 1;
    618 	if (i >= 1) {
    619 		if ((total_time[i] >= 0.5 * total_time[i - 1]) || (total_errs[i] >= HI_CONFIDENCE_MIN_ERR_CNT) ) {
    620 			stop_n = eye_cnt; /* last point will be included in linear fit */
    621 			last_point_discard = 0;
    622 		} else {
    623 			stop_n = eye_cnt - 1; /* discards the very last point */
    624 			last_point_discard = 1;
    625 		}
    626     } else {
    627 		stop_n = 1; /* there is ONLY one measurement */
    628         last_point_discard = 0;
    629     }
    630 
    631 	/* *******************************************
    632 	   Print on screen (prints RAW BER data. i.e. conf factors)
    633  */
    634 	if (verbose > 0) {
    635 		i = 0;
    636 		do {
    637 			if (total_errs[i] == 0)
    638 				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));
    639 			else if (total_errs[i] >= MAX_CLIPPED_ERR_CNT)
    640 				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));
    641 			else
    642 				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));
    643 			i++;
    644 		} while (i < stop_n);
    645 	}
    646 
    647 	/* *******************************************
    648 	   Correcting *all* BER values using confidence factors in 'ber_conf_scale' vector
    649 	   This step is done for extrapolation purposes
    650  */
    651 	for (loop_index = 0; loop_index < eye_cnt; loop_index++) {
    652 		if (total_errs[loop_index] <= 100)
    653 			bers[loop_index] = ber_conf_scale[total_errs[loop_index]] * bers[loop_index];
    654 		else if (total_errs[loop_index] > 100 && total_errs[loop_index] < 200)
    655 			bers[loop_index] = ber_conf_scale[100] * bers[loop_index];
    656 		else if (total_errs[loop_index] >= 200 && total_errs[loop_index] < 300)
    657 			bers[loop_index] = ber_conf_scale[101] * bers[loop_index];
    658 		else if (total_errs[loop_index] >= 300 && total_errs[loop_index] < 400)
    659 			bers[loop_index] = ber_conf_scale[102] * bers[loop_index];
    660 		else if (total_errs[loop_index] >= 400)
    661 			bers[loop_index] = ber_conf_scale[103] * bers[loop_index];
    662 	}
    663 
    664 	/* *******************************************
    665 	   Computes the "linearised" ber vector
    666  */
    667 	for (loop_index = 0; loop_index < eye_cnt; loop_index++)
    668 		lbers[loop_index] = (USR_DOUBLE)sqrt(-log10(bers[loop_index]));
    669 
    670 	/* *******************************************
    671 	   Assign highest data point to use
    672  */
    673 	if (first_good_ber_idx == -1)
    674 		start_n = stop_n;
    675 	else
    676 		start_n = first_good_ber_idx;
    677 
    678 
    679 
    680 	/* ******************************************************
    681 	***********  EXTRAPOLATION (START) **********************
    682 	*********************************************************
    683 	   Different data set profiles can be received by this code.
    684 	   Each case is processed accordingly here (IF-ELSE IF cases)
    685  */
    686 
    687 	/* ====> Errors encountered all the way to sampling point */
    688 	if (start_n >= eye_cnt) {
    689 		proj_case = 1;
    690 		ENULL_STRCPY(message, "No low-BER point measured");
    691 
    692 		/* confidence factor of 0.96 is applied in this case to set a LOWER bound and report accordingly.
    693 		    This factor corresponds to approximately 3000 errors @95% confidence
    694 		    For reference: factors for 900, 2000, 3000, 5000, 20000 and 50000 errors are: 0.96, 0.96, 0.97, 0.99, 0.99, respectively */
    695 		proj_ber = 0.96 * log10(bers[eye_cnt - 1]);
    696 		proj_ber_aux = proj_ber;
    697 		EFUN_PRINTF(("BER *worse* than 1e%0.2f\n", proj_ber));
    698 		EFUN_PRINTF(("No margin @ 1e-12, 1e-15 & 1e-18\n\n\n"));
    699 		fit_count = 1;
    700 	}else  {
    701 
    702 		/* ====> Only ONE measured point. Typically when the eye is wide open.
    703 		    Artificial points will be used to make extrapolation possible */
    704 		if (stop_n == 1) {
    705 			proj_case = 2;
    706 			ENULL_STRCPY(message, "Not enough points (single measured point). Using artificial point");
    707 
    708 			low_confidence = 1;
    709 			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 */
    710 			fit_count = 2;
    711 
    712 			/* Compute covariances and means... but only for two points: artificial and the single measured point */
    713 			Exy = ((margins[0] * lbers[0] + artificial_margin * artificial_lber) / 2.0);
    714 			Eyy = ((lbers[0] * lbers[0] + artificial_lber * artificial_lber) / 2.0);
    715 			Exx = ((margins[0] * margins[0] + artificial_margin * artificial_margin) / 2.0);
    716 			Ey  = ((lbers[0] + artificial_lber) / 2.0);
    717 			Ex  = ((margins[0] + artificial_margin) / 2.0);
    718 		}
    719 		/* ====> "NORMAL" case (when there are more than 1 measurements) */
    720 		else {
    721 
    722 			/* Detect and record nonmonotonic data points */
    723 			for (loop_index = 0; loop_index < stop_n; loop_index++) {
    724 				if ((loop_index > start_n) && (log10(bers[loop_index]) > log10(bers[loop_index - 1]))) {
    725 					mono_flags[loop_index] = 1;
    726 					if (first_good_ber_idx != -1)
    727 						n_mono++;
    728 				}
    729 			}
    730 
    731 			/* Finds number of MEASURED points available for extrapolation */
    732 			delta_n = (stop_n - start_n - n_mono);
    733 
    734 
    735 			/*    HIGH CONFIDENCE case */
    736 
    737 			if (delta_n >= 2) { /* there are at least 2 points to trace a line */
    738 				proj_case = 3;
    739 				ENULL_STRCPY(message, "Normal case");
    740 				low_confidence = 0;
    741 
    742 				/* Compute covariances and means */
    743 				fit_count = 0;
    744 				for (loop_index = start_n; loop_index < stop_n; loop_index++) {
    745 					if (mono_flags[loop_index] == 0) {
    746 						Exy += (margins[loop_index] * lbers[loop_index] / (USR_DOUBLE)delta_n);
    747 						Eyy += (lbers[loop_index] * lbers[loop_index] / (USR_DOUBLE)delta_n);
    748 						Exx += (margins[loop_index] * margins[loop_index] / (USR_DOUBLE)delta_n);
    749 						Ey  += (lbers[loop_index] / (USR_DOUBLE)delta_n);
    750 						Ex  += (margins[loop_index] / (USR_DOUBLE)delta_n);
    751 						fit_count++;
    752 					}
    753 				}
    754 			}
    755 			/*    LOW CONFIDENCE case */
    756 			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 */
    757 				low_confidence = 1;
    758 				if ( (first_non_clipped_errcnt_idx >= 0) && (first_non_clipped_errcnt_idx < start_n)) {
    759 					proj_case = 4;
    760 					ENULL_STRCPY(message, "Not enough points. Using first measured point for conservative estimation");
    761 					fit_count = 2;
    762 					/* Compute covariances and means... but only for two points: first and last */
    763 					Exy = ((margins[stop_n - 1] * lbers[stop_n - 1] + margins[first_non_clipped_errcnt_idx] * lbers[first_non_clipped_errcnt_idx]) / 2.0);
    764 					Eyy = ((lbers[stop_n - 1] * lbers[stop_n - 1] + lbers[first_non_clipped_errcnt_idx] * lbers[first_non_clipped_errcnt_idx]) / 2.0);
    765 					Exx = ((margins[stop_n - 1] * margins[stop_n - 1] + margins[first_non_clipped_errcnt_idx] * margins[first_non_clipped_errcnt_idx]) / 2.0);
    766 					Ey  = ((lbers[stop_n - 1] + lbers[first_non_clipped_errcnt_idx]) / 2.0);
    767 					Ex  = ((margins[stop_n - 1] + margins[first_non_clipped_errcnt_idx]) / 2.0);
    768 				} else {
    769 					proj_case = 5;
    770 					ENULL_STRCPY(message, "Not enough points (cannot use non-clipped ErrorCount point). Using artificial point");
    771 					/* Compute covariances and means... but only for two points: artificial and the single measured point */
    772 					Exy = (artificial_margin * artificial_lber) / 2.0;
    773 					Eyy = (artificial_lber * artificial_lber) / 2.0;
    774 					Exx = (artificial_margin * artificial_margin) / 2.0;
    775 					Ey  = (artificial_lber) / 2.0;
    776 					Ex  = (artificial_margin) / 2.0;
    777 					fit_count = 1;
    778 					/* This FOR loop checks for monotonicity as well */
    779 					for (loop_index = start_n; loop_index < stop_n; loop_index++) {
    780 						if (mono_flags[loop_index] == 0) {
    781 							Exy += (margins[loop_index] * lbers[loop_index] / 2.0);
    782 							Eyy += (lbers[loop_index] * lbers[loop_index] / 2.0);
    783 							Exx += (margins[loop_index] * margins[loop_index] / 2.0);
    784 							Ey  += (lbers[loop_index] / 2.0);
    785 							Ex  += (margins[loop_index] / 2.0);
    786 							fit_count++;
    787 						}
    788 					}
    789 				}
    790 			}
    791 		}
    792 
    793 		/* Compute fit slope and offset: ber = alpha*margin + beta */
    794 		alpha = (Exy - Ey * Ex) / (Exx - Ex * Ex);
    795 		beta = Ey - Ex * alpha;
    796 		/* Compute alpha2: slope of regression: margin = alpha2*ber + beta2 */
    797 		alpha2 = (Exy - Ey * Ex) / (Eyy - Ey * Ey);
    798 		/* Compute correlation index sq_r */
    799 		sq_r = alpha * alpha2;
    800 
    801 		proj_ber = pow(10, (-beta * beta));
    802 		proj_margin_12 = direction * (sqrt(-log10(1e-12)) - beta) / alpha;
    803 		proj_margin_15 = direction * (sqrt(-log10(1e-15)) - beta) / alpha;
    804 		proj_margin_18 = direction * (sqrt(-log10(1e-18)) - beta) / alpha;
    805 
    806 		/* Estimate modeled gaussian noise.
    807 
    808 		    The following is based on the Q-function model and the following table:
    809 		        Q    |    log10(BER)
    810 		    =======================
    811 		      7.033    |    -12
    812 		      7.941    |    -15
    813 		      8.757    |    -18
    814 
    815 		   Based on the above, we solve for sigma:
    816 		    7.033*sigma = u - proj_margin_12 , and
    817 		    7.941*sigma = u - proj_margin_15
    818 		 */
    819 		gauss_noise = (proj_margin_12 - proj_margin_15) / 0.908;
    820 
    821 		sq_err1 = (Eyy + (beta * beta) + (Exx * alpha * alpha) -
    822 			   (2 * Ey * beta) - (2 * Exy * alpha) + (2 * Ex * beta * alpha));
    823 		sq_err2 = 0;
    824 		for (loop_index = start_n; loop_index < stop_n; loop_index++) {
    825 			ierr = (lbers[loop_index] - (alpha * margins[loop_index] + beta));
    826 			sq_err2 += (ierr * ierr / (USR_DOUBLE)delta_n);
    827 		}
    828 
    829 		proj_ber = log10(proj_ber);
    830 		proj_ber_aux = proj_ber;
    831 
    832 		if (proj_ber < MIN_BER_TO_REPORT) {
    833 			proj_ber = MIN_BER_TO_REPORT;
    834 			ber_clipped = 1;
    835 		}
    836 
    837 		/* Extrapolated results, low confidence */
    838 		if (low_confidence == 1) {
    839 
    840 			EFUN_PRINTF(("BER(extrapolated) < 1e%0.2f\n", proj_ber));
    841 			EFUN_PRINTF(("Margin @ 1e-12    > %0.2f %s\n", (proj_ber < -12) ? _abs(proj_margin_12) : 0, unit));
    842 			EFUN_PRINTF(("Margin @ 1e-15    > %0.2f %s\n", (proj_ber < -15) ? _abs(proj_margin_15) : 0, unit));
    843 			EFUN_PRINTF(("Margin @ 1e-18    > %0.2f %s\n", (proj_ber < -18) ? _abs(proj_margin_18) : 0, unit));
    844 
    845 			/* Extrapolated results, HIGH confidence */
    846 		} else {
    847 
    848 			if (ber_clipped == 1)
    849 				EFUN_PRINTF(("BER(extrapolated) < 1e%0.2f\n", proj_ber));
    850 			else
    851 				EFUN_PRINTF(("BER(extrapolated) = 1e%0.2f\n", proj_ber));
    852 			EFUN_PRINTF(("Margin @ 1e-12    = %0.2f %s\n", (proj_ber < -12) ? _abs(proj_margin_12) : 0, unit));
    853 			EFUN_PRINTF(("Margin @ 1e-15    = %0.2f %s\n", (proj_ber < -15) ? _abs(proj_margin_15) : 0, unit));
    854 			EFUN_PRINTF(("Margin @ 1e-18    = %0.2f %s\n", (proj_ber < -18) ? _abs(proj_margin_18) : 0, unit));
    855 		}
    856 
    857 		EFUN_PRINTF(("\n\n"));
    858 
    859 		/* Print non-monotonic outliers */
    860 		if (n_mono != 0) {
    861 			EFUN_PRINTF(("Detected non-monotonicity at { "));
    862 			for (loop_index = start_n; loop_index < stop_n; loop_index++)
    863 				if (mono_flags[loop_index] == 1)
    864 					EFUN_PRINTF(("%0.2f ", margins[loop_index]));
    865 			EFUN_PRINTF(("} %s\n\n\n", unit));
    866 		}
    867 
    868 	}
    869 	/* *******************************************
    870 	 ***********  EXTRAPOLATION (END) *************
    871  */
    872 
    873 
    874 
    875 	/* SUMMARY (for debugging purposes */
    876 	if (verbose > 2) EFUN_PRINTF(("\t=====> DEBUG INFO (start)\n\n"));
    877 	if (verbose > 2) {
    878 		EFUN_PRINTF((" loop   Margin      total_errors   time(sec)  logBER       lber"));
    879 		for (loop_index = 0; loop_index < stop_n + last_point_discard; loop_index++)
    880 			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]));
    881 		EFUN_PRINTF(("\n\n"));
    882 	}
    883 	if (verbose > 2) EFUN_PRINTF(("Max Offset = %d\n", max_offset));
    884 	if (verbose > 2) EFUN_PRINTF(("ber_clipped: %d, Projected BER (proj_ber_aux) = %.2f\n", ber_clipped, proj_ber_aux));
    885 	if (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)));
    886 	if (verbose > 2) EFUN_PRINTF(("first small errcnt idx at %d, errors = %d\n", first_small_errcnt_idx, ((first_small_errcnt_idx >= 0) ? total_errs[first_small_errcnt_idx] : -1)));
    887 	if (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",
    888 				      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));
    889 	if (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));
    890 	if (verbose > 2) EFUN_PRINTF(("%s\n", message));
    891 	if (verbose > 2) EFUN_PRINTF(("proj_case %d\n", proj_case));
    892 	if (verbose > 2) EFUN_PRINTF(("\n\t=====> DEBUG INFO (end)\n\n"));
    893 	EFUN_PRINTF(("\n\n\n"));
    894 
    895 
    896 
    897 #else
    898 	(void)rate;
    899 	(void)ber_scan_mode;
    900 	(void)max_offset;
    901 
    902 	EFUN_PRINTF(("This function needs SERDES_API_FLOATING_POINT define to operate \n"));
    903 
    904 	if (!total_errs || !total_time )
    905 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
    906 
    907 #endif
    908 	return ERR_CODE_NONE;
    909 
    910 }
    911 
    912 
    913 
    914 
    915 /*****************************/
    916 /*  Display Lane/Core State  */
    917 /*****************************/
    918 
    919 err_code_t falcon_tsc_display_lane_state_hdr (const phymod_access_t *pa){
    920 	EFUN_PRINTF(("LN "));
    921 	EFUN_PRINTF(("(CDRxN      , UC_CFG,RST,STP)  "));
    922 
    923 	EFUN_PRINTF(("SD LCK RXPPM "));
    924 	EFUN_PRINTF(("CLK90 CLKP1 "));
    925 	EFUN_PRINTF(("PF(M,L)  "));
    926 	EFUN_PRINTF(("VGA DCO "));
    927 	EFUN_PRINTF(("P1mV "));
    928 	EFUN_PRINTF(("M1mV "));
    929 	EFUN_PRINTF((" DFE(1,2,3,4,5,6)        "));
    930 	EFUN_PRINTF(("TXPPM "));
    931 	EFUN_PRINTF(("TXEQ(n1,m,p1,2,3) "));
    932 	EFUN_PRINTF(("TXAMP "));
    933 	EFUN_PRINTF(("  EYE(L,R,U,D)  "));
    934 	EFUN_PRINTF(("LINK_TIME"));
    935 	EFUN_PRINTF(("\n"));
    936 	return ERR_CODE_NONE;
    937 }
    938 
    939 err_code_t falcon_tsc_display_lane_state_legend (const phymod_access_t *pa){
    940 	EFUN_PRINTF(("\n"));
    941 	EFUN_PRINTF(("**********************************************************************************************\n"));
    942 	EFUN_PRINTF(("****                Legend of Entries in display_lane_state()                             ****\n"));
    943 	EFUN_PRINTF(("**********************************************************************************************\n"));
    944 	EFUN_PRINTF(("LN        : lane index within IP core\n"));
    945 	EFUN_PRINTF(("CDRxN     : CDR type x OSR ratio\n"));
    946 	EFUN_PRINTF(("UC_CFG    : micro lane configuration variable\n"));
    947 	EFUN_PRINTF(("RST       : Reset State{reset_active, reset_occured, reset_held}\n"));
    948 	EFUN_PRINTF(("STP       : uC Stopped State\n"));
    949 	EFUN_PRINTF(("SD        : signal detect\n"));
    950 	EFUN_PRINTF(("LCK       : pmd_rx_lock\n"));
    951 	EFUN_PRINTF(("RXPPM     : Frequency offset of local reference clock with respect to RX data in ppm\n"));
    952 	EFUN_PRINTF(("CLK90     : Delay of zero crossing slicer, m1, wrt to data in PI codes\n"));
    953 	EFUN_PRINTF(("CLKP1     : Delay of diagnostic/lms slicer, p1, wrt to data in PI codes\n"));
    954 	EFUN_PRINTF(("PF(M,L)   : Peaking Filter Main (0..15) and Low Frequency (0..7) settings\n"));
    955 	EFUN_PRINTF(("VGA       : Variable Gain Amplifier settings (0..39)\n"));
    956 	EFUN_PRINTF(("DCO       : DC offset DAC control value\n"));
    957 	EFUN_PRINTF(("P1mV      : Vertical threshold voltage of p1 slicer\n"));
    958 	EFUN_PRINTF(("M1mV      : Vertical threshold voltage of m1 slicer\n"));
    959 	EFUN_PRINTF(("DFE taps  : ISI correction taps in units of 2.35mV\n"));
    960 	EFUN_PRINTF(("TXPPM            : Frequency offset of local reference clock with respect to TX data in ppm\n"));
    961 	EFUN_PRINTF(("TXEQ(n1,m,p1,p2,p3) : TX equalization FIR tap weights in units of 1Vpp/160 units\n"));
    962 	EFUN_PRINTF(("TXAMP : TX amplitude, Drivermode\n"));
    963 	EFUN_PRINTF(("EYE(L,R,U,D)     : Eye margin @ 1e-5 as seen by internal diagnostic slicer in mUI and mV\n"));
    964 	EFUN_PRINTF(("LINK_TIME        : Link time in milliseconds\n"));
    965 	EFUN_PRINTF(("**********************************************************************************************\n"));
    966 	return ERR_CODE_NONE;
    967 }
    968 
    969 err_code_t falcon_tsc_display_lane_state (const phymod_access_t *pa){
    970 	err_code_t err_code = _falcon_tsc_display_lane_state_no_newline (pa );
    971 
    972 	EFUN_PRINTF(("\n"));
    973 	return err_code;
    974 }
    975 
    976 err_code_t falcon_tsc_get_eye_margin_est (const phymod_access_t *pa, int *left_eye_mUI, int *right_eye_mUI, int *upper_eye_mV, int *lower_eye_mV){
    977 	uint8_t ladder_range = 0;
    978 
    979 
    980 	ESTM(*left_eye_mUI = _eye_to_mUI (pa, rdv_usr_sts_heye_left()));
    981 	ESTM(*right_eye_mUI = _eye_to_mUI (pa, rdv_usr_sts_heye_right()));
    982 	ESTM(*upper_eye_mV = _eye_to_mV (pa, rdv_usr_sts_veye_upper(), ladder_range));
    983 	ESTM(*lower_eye_mV = _eye_to_mV (pa, rdv_usr_sts_veye_lower(), ladder_range));
    984 	return ERR_CODE_NONE;
    985 }
    986 
    987 err_code_t falcon_tsc_display_core_state_hdr (const phymod_access_t *pa){
    988 
    989 	EFUN_PRINTF(("SerDes type = %s\n", "falcon_tsc"));
    990 
    991     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\n"));
    992 	return ERR_CODE_NONE;
    993 }
    994 
    995 err_code_t falcon_tsc_display_core_state_line (const phymod_access_t *pa){
    996 	err_code_t err_code = _falcon_tsc_display_core_state_no_newline (pa );
    997 
    998 	EFUN_PRINTF(("\n"));
    999 	return err_code;
   1000 }
   1001 
   1002 err_code_t falcon_tsc_display_core_state_legend (const phymod_access_t *pa){
   1003 	EFUN_PRINTF(("\n"));
   1004 	EFUN_PRINTF(("**************************************************************************************************************\n"));
   1005 	EFUN_PRINTF(("****                          Legend of Entries in display_core_state()                                   ****\n"));
   1006 	EFUN_PRINTF(("**************************************************************************************************************\n"));
   1007 #ifdef SERDES_DUAL_PLLS
   1008     EFUN_PRINTF(("*  RST              : Core Reset State PLL0{active,occured,held}, Core Reset State PLL1{active,occured,held} *\n"));
   1009 #else
   1010 	EFUN_PRINTF(("*  RST              : Core DP Reset State{reset_active, reset_occured, reset_held}                           *\n"));
   1011 #endif
   1012 	EFUN_PRINTF(("*  ST               : Core uC Status byte(hex)                                                               *\n"));
   1013 	EFUN_PRINTF(("*  PLL_PWDN         : PLL Powerdown Control Bit (active high)                                                *\n"));
   1014 	EFUN_PRINTF(("*  UC_ATV           : UC Active bit                                                                          *\n"));
   1015 	EFUN_PRINTF(("*  COM_CLK          : COM Clock frequency in MHz                                                             *\n"));
   1016 	EFUN_PRINTF(("*  UCODE_VER        : Microcode Version [majorversion_minorversion]                                          *\n"));
   1017     EFUN_PRINTF(("*  API_VER          : API Version                                                                            *\n"));
   1018 	EFUN_PRINTF(("*  AFE_VER          : AFE Hardware Vesrion                                                                   *\n"));
   1019 	EFUN_PRINTF(("*  LIVE_TEMP        : Live Die temperature in Celsius                                                        *\n"));
   1020 	EFUN_PRINTF(("*  AVG_TMON         : uC Temp_idx, Average temperature in Celsius                                            *\n"));
   1021 	EFUN_PRINTF(("*  RESCAL           : Analog Resistor Calibration value                                                      *\n"));
   1022 	EFUN_PRINTF(("*  VCO_RATE         : uC VCO Rate in GHz (approximate)                                                       *\n"));
   1023 	EFUN_PRINTF(("*  ANA_VCO_RANGE    : Analog VCO Range                                                                       *\n"));
   1024 	EFUN_PRINTF(("*  PLL_DIV          : (Register Value) Actual PLL Divider Value                                              *\n"));
   1025 	EFUN_PRINTF(("*  PLL_Lock         : PLL Lock                                                                               *\n"));
   1026 
   1027 	EFUN_PRINTF(("**************************************************************************************************************\n"));
   1028 	return ERR_CODE_NONE;
   1029 }
   1030 
   1031 /**********************************************/
   1032 /*  Display Lane/Core Config and Debug Status */
   1033 /**********************************************/
   1034 
   1035 err_code_t falcon_tsc_display_core_config (const phymod_access_t *pa){
   1036     uint16_t vco_mhz;
   1037 	EFUN_PRINTF(("\n\n***********************************\n"  ));
   1038 	EFUN_PRINTF((    "**** SERDES CORE CONFIGURATION ****\n"  ));
   1039 	EFUN_PRINTF((    "***********************************\n\n"));
   1040 	{
   1041 		struct   falcon_tsc_uc_core_config_st core_cfg;
   1042 		ENULL_MEMSET(&core_cfg, 0, sizeof(core_cfg));
   1043 		EFUN(falcon_tsc_get_uc_core_config (pa, &core_cfg));
   1044 		{
   1045 			vco_mhz = (uint16_t)core_cfg.vco_rate_in_Mhz;
   1046 			EFUN_PRINTF((    "uC Config VCO Rate   = %d (~%d.%03dGHz)\n", core_cfg.field.vco_rate
   1047 					 , (vco_mhz / 1000)
   1048 					 , (vco_mhz % 1000)                ));
   1049 			EFUN_PRINTF((    "Core Config from PCS = %d\n\n", core_cfg.field.core_cfg_from_pcs));
   1050 		}
   1051 	}
   1052 	ESTM_PRINTF((    "Lane Addr 0          = %d\n", rdc_lane_addr_0()   ));
   1053 	ESTM_PRINTF((    "Lane Addr 1          = %d\n", rdc_lane_addr_1()   ));
   1054 	ESTM_PRINTF((    "Lane Addr 2          = %d\n", rdc_lane_addr_2()   ));
   1055 	ESTM_PRINTF((    "Lane Addr 3          = %d\n", rdc_lane_addr_3()   ));
   1056 	ESTM_PRINTF((    "TX Lane Map 0        = %d\n", rdc_tx_lane_map_0() ));
   1057 	ESTM_PRINTF((    "TX Lane Map 1        = %d\n", rdc_tx_lane_map_1() ));
   1058 	ESTM_PRINTF((    "TX Lane Map 2        = %d\n", rdc_tx_lane_map_2() ));
   1059 	ESTM_PRINTF((    "TX Lane Map 3        = %d\n\n", rdc_tx_lane_map_3() ));
   1060 	return ERR_CODE_NONE;
   1061 }
   1062 
   1063 
   1064 err_code_t falcon_tsc_display_lane_config (const phymod_access_t *pa){
   1065 	struct falcon_tsc_uc_lane_config_st lane_cfg;
   1066 
   1067 	ENULL_MEMSET(&lane_cfg, 0, sizeof(lane_cfg));
   1068 
   1069 	EFUN_PRINTF(("\n\n*************************************\n"                                          ));
   1070 	ESTM_PRINTF((   "**** SERDES LANE %d CONFIGURATION ****\n", falcon_tsc_get_lane (pa )                     ));
   1071 	EFUN_PRINTF((    "*************************************\n\n"                                        ));
   1072 	EFUN(                                                         falcon_tsc_get_uc_lane_cfg (pa, &lane_cfg)      );
   1073 	EFUN_PRINTF((    "Auto-Neg Enabled            = %d\n", lane_cfg.field.an_enabled             ));
   1074 	EFUN_PRINTF((    "DFE on                      = %d\n", lane_cfg.field.dfe_on                 ));
   1075 	EFUN_PRINTF((    "DFE low power mode          = %d\n", lane_cfg.field.dfe_lp_mode            ));
   1076 	EFUN_PRINTF((    "Brdfe_on                    = %d\n", lane_cfg.field.force_brdfe_on         ));
   1077 	EFUN_PRINTF((    "Media Type                  = %d\n", lane_cfg.field.media_type             ));
   1078 	EFUN_PRINTF((    "Unreliable LOS              = %d\n", lane_cfg.field.unreliable_los         ));
   1079 	EFUN_PRINTF((    "Scrambling Disable          = %d\n", lane_cfg.field.scrambling_dis         ));
   1080 	EFUN_PRINTF((    "Lane Config from PCS        = %d\n\n", lane_cfg.field.lane_cfg_from_pcs      ));
   1081 #if defined(SERDES_ENABLE_FAST_LINK_RECOVERY)
   1082     ESTM_PRINTF((    "Fast Link Recovery Enable   = %d\n"       , rdv_usr_ctrl_fast_link_recovery_byte() & 1));
   1083 #endif
   1084 	EFUN_PRINTF((    "CL72 Auto Polarity   Enable = %d\n", lane_cfg.field.cl72_auto_polarity_en  ));
   1085 	EFUN_PRINTF((    "CL72 Restart timeout Enable = %d\n", lane_cfg.field.cl72_restart_timeout_en));
   1086 	EFUN_PRINTF((    "Enable Short Channel OSx1   = %d\n", lane_cfg.field.en_short_chn_osx1      ));
   1087 	ESTM_PRINTF((    "CL93/72 Training Enable     = %d\n", rd_cl93n72_ieee_training_enable()     ));
   1088 
   1089 	ESTM_PRINTF((    "EEE Mode Enable             = %d\n", rd_eee_mode_en()                      ));
   1090 	ESTM_PRINTF((    "OSR Mode Force              = %d\n", rd_osr_mode_frc()                     ));
   1091 	ESTM_PRINTF((    "OSR Mode Force Val          = %d\n", rd_osr_mode_frc_val()                 ));
   1092 	ESTM_PRINTF((    "TX Polarity Invert          = %d\n", rd_tx_pmd_dp_invert()                 ));
   1093 	ESTM_PRINTF((    "RX Polarity Invert          = %d\n\n", rd_rx_pmd_dp_invert()                 ));
   1094 	ESTM_PRINTF((    "TXFIR Post2                 = %d\n", rd_txfir_post2()                      ));
   1095 	ESTM_PRINTF((    "TXFIR Post3                 = %d\n", rd_txfir_post3()                      ));
   1096 	ESTM_PRINTF((    "TXFIR Main                  = %d\n", rd_cl93n72_txfir_main()               ));
   1097 	ESTM_PRINTF((    "TXFIR Pre                   = %d\n", rd_cl93n72_txfir_pre()                ));
   1098 	ESTM_PRINTF((    "TXFIR Post                  = %d\n", rd_cl93n72_txfir_post()               ));
   1099 	return ERR_CODE_NONE;
   1100 }
   1101 
   1102 
   1103 err_code_t falcon_tsc_display_core_state (const phymod_access_t *pa){
   1104 	EFUN(falcon_tsc_display_core_state_hdr (pa ));
   1105 	EFUN(falcon_tsc_display_core_state_line (pa ));
   1106 	EFUN(falcon_tsc_display_core_state_legend (pa ));
   1107 	return ERR_CODE_NONE;
   1108 }
   1109 
   1110 
   1111 
   1112 err_code_t falcon_tsc_display_lane_debug_status (const phymod_access_t *pa){
   1113 	/* startup */
   1114 	struct falcon_tsc_usr_ctrl_disable_functions_st ds;
   1115 	struct falcon_tsc_usr_ctrl_disable_dfe_functions_st dsd;
   1116 	/* steady state */
   1117 	struct falcon_tsc_usr_ctrl_disable_functions_st dss;
   1118 	struct falcon_tsc_usr_ctrl_disable_dfe_functions_st dssd;
   1119 
   1120 	ENULL_MEMSET(&ds, 0, sizeof(ds  ));
   1121 	ENULL_MEMSET(&dsd, 0, sizeof(dsd ));
   1122 	ENULL_MEMSET(&dss, 0, sizeof(dss ));
   1123 	ENULL_MEMSET(&dssd, 0, sizeof(dssd));
   1124 
   1125 	EFUN_PRINTF(("\n\n************************************\n"                                                     ));
   1126 	ESTM_PRINTF((   "**** SERDES LANE %d DEBUG STATUS ****\n", falcon_tsc_get_lane (pa )                   ));
   1127 	EFUN_PRINTF((    "************************************\n\n"                                                   ));
   1128 	ESTM_PRINTF((    "Restart Count                                = %d\n", rdv_usr_sts_restart_counter()       ));
   1129 	ESTM_PRINTF((    "Reset Count                                  = %d\n", rdv_usr_sts_reset_counter()         ));
   1130 	ESTM_PRINTF((    "PMD Lock Count                               = %d\n\n", rdv_usr_sts_pmd_lock_counter()      ));
   1131 	EFUN(falcon_tsc_get_usr_ctrl_disable_startup (pa, &ds));
   1132 	EFUN_PRINTF((    "Disable Startup PF Adaptation                = %d\n", ds.field.pf_adaptation              ));
   1133 	EFUN_PRINTF((    "Disable Startup PF2 Adaptation               = %d\n", ds.field.pf2_adaptation             ));
   1134 	EFUN_PRINTF((    "Disable Startup DC Adaptation                = %d\n", ds.field.dc_adaptation              ));
   1135 	EFUN_PRINTF((    "Disable Startup VGA Adaptation               = %d\n", ds.field.vga_adaptation             ));
   1136 	EFUN_PRINTF((    "Disable Startup Slicer vOffset Tuning        = %d\n", ds.field.slicer_voffset_tuning      ));
   1137 	EFUN_PRINTF((    "Disable Startup Slicer hOffset Tuning        = %d\n", ds.field.slicer_hoffset_tuning      ));
   1138 	EFUN_PRINTF((    "Disable Startup Phase offset Adaptation      = %d\n", ds.field.phase_offset_adaptation    ));
   1139 	EFUN_PRINTF((    "Disable Startup Eye Adaptaion                = %d\n", ds.field.eye_adaptation             ));
   1140 	EFUN_PRINTF((    "Disable Startup All Adaptaion                = %d\n\n", ds.field.all_adaptation             ));
   1141 	EFUN(                                                            falcon_tsc_get_usr_ctrl_disable_startup_dfe (pa, &dsd) );
   1142 	EFUN_PRINTF((    "Disable Startup DFE Tap1 Adaptation          = %d\n", dsd.field.dfe_tap1_adaptation       ));
   1143 	EFUN_PRINTF((    "Disable Startup DFE FX Taps Adaptation       = %d\n", dsd.field.dfe_fx_taps_adaptation    ));
   1144 	EFUN_PRINTF((    "Disable Startup DFE FL Taps Adaptation       = %d\n", dsd.field.dfe_fl_taps_adaptation    ));
   1145 	EFUN_PRINTF((    "Disable Startup DFE Tap DCD                  = %d\n", dsd.field.dfe_dcd_adaptation        ));
   1146 	EFUN(                                                           falcon_tsc_get_usr_ctrl_disable_steady_state (pa, &dss) );
   1147 	EFUN_PRINTF((    "Disable Steady State PF Adaptation           = %d\n", dss.field.pf_adaptation             ));
   1148 	EFUN_PRINTF((    "Disable Steady State PF2 Adaptation          = %d\n", dss.field.pf2_adaptation            ));
   1149 	EFUN_PRINTF((    "Disable Steady State DC Adaptation           = %d\n", dss.field.dc_adaptation             ));
   1150 	EFUN_PRINTF((    "Disable Steady State VGA Adaptation          = %d\n", dss.field.vga_adaptation            ));
   1151 	EFUN_PRINTF((    "Disable Steady State Slicer vOffset Tuning   = %d\n", dss.field.slicer_voffset_tuning     ));
   1152 	EFUN_PRINTF((    "Disable Steady State Slicer hOffset Tuning   = %d\n", dss.field.slicer_hoffset_tuning     ));
   1153 	EFUN_PRINTF((    "Disable Steady State Phase offset Adaptation = %d\n", dss.field.phase_offset_adaptation   ));
   1154 	EFUN_PRINTF((    "Disable Steady State Eye Adaptaion           = %d\n", dss.field.eye_adaptation            ));
   1155 	EFUN_PRINTF((    "Disable Steady State All Adaptaion           = %d\n\n", dss.field.all_adaptation            ));
   1156 	EFUN(                                                      falcon_tsc_get_usr_ctrl_disable_steady_state_dfe (pa, &dssd) );
   1157 	EFUN_PRINTF((    "Disable Steady State DFE Tap1 Adaptation     = %d\n", dssd.field.dfe_tap1_adaptation      ));
   1158 	EFUN_PRINTF((    "Disable Steady State DFE FX Taps Adaptation  = %d\n", dssd.field.dfe_fx_taps_adaptation   ));
   1159 	EFUN_PRINTF((    "Disable Steady State DFE FL Taps Adaptation  = %d\n", dssd.field.dfe_fl_taps_adaptation   ));
   1160 	EFUN_PRINTF((    "Disable Steady State DFE Tap DCD             = %d\n\n", dssd.field.dfe_dcd_adaptation       ));
   1161 	ESTM_PRINTF((    "Clk90 offset Adjust                          = %d\n", rdv_usr_ctrl_clk90_offset_adjust()  ));
   1162 	ESTM_PRINTF((    "Clk90 offset Override                        = %d\n", rdv_usr_ctrl_clk90_offset_override()));
   1163 	ESTM_PRINTF((    "Lane Event Log Level                         = %d\n", rdv_usr_ctrl_lane_event_log_level() ));
   1164 
   1165 	return ERR_CODE_NONE;
   1166 }
   1167 
   1168 
   1169 
   1170 /*************************/
   1171 /*  Stop/Resume uC Lane  */
   1172 /*************************/
   1173 
   1174 err_code_t falcon_tsc_stop_uc_lane (const phymod_access_t *pa, uint8_t enable){
   1175 
   1176 	if (enable)
   1177 		return falcon_tsc_pmd_uc_control (pa, CMD_UC_CTRL_STOP_GRACEFULLY, 100);
   1178 	else
   1179 		return falcon_tsc_pmd_uc_control (pa, CMD_UC_CTRL_RESUME, 50);
   1180 }
   1181 
   1182 
   1183 err_code_t falcon_tsc_stop_uc_lane_status (const phymod_access_t *pa, uint8_t *uc_lane_stopped){
   1184 
   1185 	if (!uc_lane_stopped)
   1186 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1187 
   1188 	ESTM(*uc_lane_stopped = rdv_usr_sts_micro_stopped());
   1189 
   1190 	return ERR_CODE_NONE;
   1191 }
   1192 
   1193 
   1194 /*******************************/
   1195 /*  Stop/Resume RX Adaptation  */
   1196 /*******************************/
   1197 
   1198 err_code_t falcon_tsc_stop_rx_adaptation (const phymod_access_t *pa, uint8_t enable){
   1199 
   1200 	if (enable)
   1201 		return falcon_tsc_pmd_uc_control (pa, CMD_UC_CTRL_STOP_GRACEFULLY, 100);
   1202 	else
   1203 		return falcon_tsc_pmd_uc_control (pa, CMD_UC_CTRL_RESUME, 50);
   1204 }
   1205 
   1206 err_code_t falcon_tsc_request_stop_rx_adaptation (const phymod_access_t *pa){
   1207 
   1208 	return falcon_tsc_pmd_uc_control_return_immediate (pa, CMD_UC_CTRL_STOP_GRACEFULLY);
   1209 }
   1210 
   1211 
   1212 /**********************/
   1213 /*  uCode CRC Verify  */
   1214 /**********************/
   1215 
   1216 err_code_t falcon_tsc_ucode_crc_verify (const phymod_access_t *pa, uint16_t ucode_len, uint16_t expected_crc_value){
   1217 	uint16_t calc_crc;
   1218 
   1219 	EFUN(falcon_tsc_pmd_uc_cmd_with_data (pa, CMD_CALC_CRC, 0, ucode_len, 200));
   1220 
   1221 	ESTM(calc_crc = rd_uc_dsc_data());
   1222 	if (calc_crc != expected_crc_value) {
   1223 		EFUN_PRINTF(("UC CRC did not match expected=%04x : calculated=%04x\n", expected_crc_value, calc_crc));
   1224 		return _error(ERR_CODE_UC_CRC_NOT_MATCH);
   1225 	}
   1226 
   1227 	return ERR_CODE_NONE;
   1228 }
   1229 
   1230 err_code_t falcon_tsc_start_ucode_crc_calc (const phymod_access_t *pa, uint16_t ucode_len){
   1231 
   1232 	EFUN(falcon_tsc_pmd_uc_cmd_with_data_return_immediate (pa, CMD_CALC_CRC, 0, ucode_len)); /* Invoke Calculate CRC command and return control immediately */
   1233 	return ERR_CODE_NONE;
   1234 }
   1235 
   1236 err_code_t falcon_tsc_check_ucode_crc (const phymod_access_t *pa, uint16_t expected_crc_value, uint32_t timeout_ms){
   1237 	uint16_t calc_crc;
   1238 	err_code_t err_code;
   1239 
   1240 	err_code = falcon_tsc_poll_uc_dsc_ready_for_cmd_equals_1 (pa, timeout_ms); /* Poll for uc_dsc_ready_for_cmd = 1 to indicate falcon_tsc ready for command */
   1241 	if (err_code) {
   1242 		EFUN_PRINTF(("ERROR : DSC ready for command timed out. Previous uC command not finished yet\n"));
   1243 		return err_code;
   1244 	}
   1245 	ESTM(calc_crc = rd_uc_dsc_data());
   1246 	if (calc_crc != expected_crc_value) {
   1247 		EFUN_PRINTF(("UC CRC did not match expected=%04x : calculated=%04x\n", expected_crc_value, calc_crc));
   1248 		return _error(ERR_CODE_UC_CRC_NOT_MATCH);
   1249 	}
   1250 
   1251 	return ERR_CODE_NONE;
   1252 }
   1253 
   1254 
   1255 /******************************************************/
   1256 /*  Commands through Serdes FW DSC Command Interface  */
   1257 /******************************************************/
   1258 
   1259 err_code_t falcon_tsc_pmd_uc_cmd_return_immediate (const phymod_access_t *pa, enum srds_pmd_uc_cmd_enum cmd, uint8_t supp_info){
   1260 	err_code_t err_code;
   1261 	uint16_t cmddata;
   1262 
   1263 	err_code = falcon_tsc_poll_uc_dsc_ready_for_cmd_equals_1 (pa, 1); /* Poll for uc_dsc_ready_for_cmd = 1 to indicate falcon_tsc ready for command */
   1264 	if (err_code) {
   1265 		EFUN_PRINTF(("ERROR : DSC ready for command timed out (before cmd) cmd = %d, supp_info = x%02x err=%d !\n", cmd, supp_info, err_code));
   1266 		return err_code;
   1267 	}
   1268 /*EFUN(wr_uc_dsc_supp_info(supp_info)); */                     /* Supplement info field */
   1269 /*EFUN(wr_uc_dsc_error_found(0x0)    ); */                     /* Clear error found field */
   1270 /*EFUN(wr_uc_dsc_gp_uc_req(cmd)      ); */                     /* Set command code */
   1271 /*EFUN(wr_uc_dsc_ready_for_cmd(0x0)  ); */                     /* Issue command, by clearing "ready for command" field */
   1272 	cmddata = (((uint16_t)supp_info) << 8) | (uint16_t)cmd;         /* Combine writes to single write instead of 4 RMW */
   1273 
   1274 	EFUN(falcon_tsc_pmd_wr_reg (pa, DSC_A_DSC_UC_CTRL, cmddata));        /* This address is same for Eagle, and all Merlin */
   1275 
   1276 	return ERR_CODE_NONE;
   1277 }
   1278 
   1279 err_code_t falcon_tsc_pmd_uc_cmd (const phymod_access_t *pa, enum srds_pmd_uc_cmd_enum cmd, uint8_t supp_info, uint32_t timeout_ms){
   1280 
   1281 	EFUN(falcon_tsc_pmd_uc_cmd_return_immediate (pa, cmd, supp_info));           /* Invoke falcon_tsc_uc_cmd and return control immediately */
   1282 
   1283 	EFUN(falcon_tsc_poll_uc_dsc_ready_for_cmd_equals_1 (pa, timeout_ms));        /* Poll for uc_dsc_ready_for_cmd = 1 to indicate falcon_tsc ready for command */
   1284 	return ERR_CODE_NONE;
   1285 }
   1286 
   1287 
   1288 err_code_t falcon_tsc_pmd_uc_cmd_with_data_return_immediate (const phymod_access_t *pa, enum srds_pmd_uc_cmd_enum cmd, uint8_t supp_info, uint16_t data){
   1289 	uint16_t cmddata;
   1290 	err_code_t err_code;
   1291 
   1292 	err_code = falcon_tsc_poll_uc_dsc_ready_for_cmd_equals_1 (pa, 1); /* Poll for uc_dsc_ready_for_cmd = 1 to indicate falcon_tsc ready for command */
   1293 	if (err_code) {
   1294 		EFUN_PRINTF(("ERROR : DSC ready for command timed out (before cmd) cmd = %d, supp_info = x%02x, data = x%04x err=%d !\n", cmd, supp_info, data, err_code));
   1295 		return err_code;
   1296 	}
   1297 
   1298 	EFUN(wr_uc_dsc_data(data));                            /* Write value written to uc_dsc_data field */
   1299 /*EFUN(wr_uc_dsc_supp_info(supp_info)); */                     /* Supplement info field */
   1300 /*EFUN(wr_uc_dsc_error_found(0x0));     */                     /* Clear error found field */
   1301 /*EFUN(wr_uc_dsc_gp_uc_req(cmd));       */                     /* Set command code */
   1302 /*EFUN(wr_uc_dsc_ready_for_cmd(0x0));   */                     /* Issue command, by clearing "ready for command" field */
   1303 	cmddata = (((uint16_t)supp_info) << 8) | (uint16_t)cmd;         /* Combine writes to single write instead of 4 RMW */
   1304 
   1305 	EFUN(falcon_tsc_pmd_wr_reg (pa, DSC_A_DSC_UC_CTRL, cmddata));        /* This address is same for Eagle, and all Merlin */
   1306 
   1307 	return ERR_CODE_NONE;
   1308 }
   1309 
   1310 
   1311 err_code_t falcon_tsc_pmd_uc_cmd_with_data (const phymod_access_t *pa, enum srds_pmd_uc_cmd_enum cmd, uint8_t supp_info, uint16_t data, uint32_t timeout_ms){
   1312 
   1313 	EFUN(falcon_tsc_pmd_uc_cmd_with_data_return_immediate (pa, cmd, supp_info, data));   /* Invoke falcon_tsc_uc_cmd and return control immediately */
   1314 
   1315 	EFUN(falcon_tsc_poll_uc_dsc_ready_for_cmd_equals_1 (pa, timeout_ms));                /* Poll for uc_dsc_ready_for_cmd = 1 to indicate falcon_tsc ready for command */
   1316 	return ERR_CODE_NONE;
   1317 }
   1318 
   1319 err_code_t falcon_tsc_pmd_uc_control_return_immediate (const phymod_access_t *pa, enum srds_pmd_uc_ctrl_cmd_enum control){
   1320 	return falcon_tsc_pmd_uc_cmd_return_immediate (pa, CMD_UC_CTRL, (uint8_t)control);
   1321 }
   1322 
   1323 err_code_t falcon_tsc_pmd_uc_control (const phymod_access_t *pa, enum srds_pmd_uc_ctrl_cmd_enum control, uint32_t timeout_ms){
   1324 	return falcon_tsc_pmd_uc_cmd (pa, CMD_UC_CTRL, (uint8_t)control, timeout_ms);
   1325 }
   1326 
   1327 err_code_t falcon_tsc_pmd_uc_diag_cmd (const phymod_access_t *pa, enum srds_pmd_uc_diag_cmd_enum control, uint32_t timeout_ms){
   1328 	return falcon_tsc_pmd_uc_cmd (pa, CMD_DIAG_EN, (uint8_t)control, timeout_ms);
   1329 }
   1330 
   1331 
   1332 /************************************************************/
   1333 /*      Serdes IP RAM access - Lane RAM Variables           */
   1334 /*----------------------------------------------------------*/
   1335 /*   - through Micro Register Interface for PMD IPs         */
   1336 /*   - through Serdes FW DSC Command Interface for Gallardo */
   1337 /************************************************************/
   1338 
   1339 /* Micro RAM Lane Byte Read */
   1340 uint8_t falcon_tsc_rdbl_uc_var (const phymod_access_t *pa, err_code_t *err_code_p, uint16_t addr){
   1341 	uint8_t rddata;
   1342 
   1343 	if (!err_code_p)
   1344 		return 0;
   1345 
   1346 	EPSTM(rddata = falcon_tsc_rdb_uc_ram (pa, err_code_p, (LANE_VAR_RAM_BASE + addr + (falcon_tsc_get_lane (pa ) * LANE_VAR_RAM_SIZE)))); /* Use Micro register interface for reading RAM */
   1347 
   1348 	return rddata;
   1349 }
   1350 
   1351 /* Micro RAM Lane Byte Signed Read */
   1352 int8_t falcon_tsc_rdbls_uc_var (const phymod_access_t *pa, err_code_t *err_code_p, uint16_t addr){
   1353 	return (int8_t)falcon_tsc_rdbl_uc_var (pa, err_code_p, addr);
   1354 }
   1355 
   1356 /* Micro RAM Lane Word Read */
   1357 uint16_t falcon_tsc_rdwl_uc_var (const phymod_access_t *pa, err_code_t *err_code_p, uint16_t addr){
   1358 	uint16_t rddata;
   1359 
   1360 	if (!err_code_p)
   1361 		return 0;
   1362 
   1363 	if (addr % 2 != 0) {                                                        /* Validate even address */
   1364 		*err_code_p = ERR_CODE_INVALID_RAM_ADDR;
   1365 		return 0;
   1366 	}
   1367 
   1368 	EPSTM(rddata = falcon_tsc_rdw_uc_ram (pa, err_code_p, (LANE_VAR_RAM_BASE + addr + (falcon_tsc_get_lane (pa ) * LANE_VAR_RAM_SIZE)))); /* Use Micro register interface for reading RAM */
   1369 
   1370 	return rddata;
   1371 }
   1372 
   1373 
   1374 /* Micro RAM Lane Word Signed Read */
   1375 int16_t falcon_tsc_rdwls_uc_var (const phymod_access_t *pa, err_code_t *err_code_p, uint16_t addr){
   1376 	return (int16_t)falcon_tsc_rdwl_uc_var (pa, err_code_p, addr);
   1377 }
   1378 
   1379 /* Micro RAM Lane Byte Write */
   1380 err_code_t falcon_tsc_wrbl_uc_var (const phymod_access_t *pa, uint16_t addr, uint8_t wr_val){
   1381 
   1382 
   1383 	if (addr < LANE_VAR_RAM_SIZE)
   1384 		return falcon_tsc_wrb_uc_ram (pa, (LANE_VAR_RAM_BASE + addr + (falcon_tsc_get_lane (pa ) * LANE_VAR_RAM_SIZE)), wr_val); /* Use Micro register interface for writing RAM */
   1385 	else
   1386 		return _error(ERR_CODE_INVALID_RAM_ADDR);
   1387 
   1388 }
   1389 
   1390 /* Micro RAM Lane Byte Signed Write */
   1391 err_code_t falcon_tsc_wrbls_uc_var (const phymod_access_t *pa, uint16_t addr, int8_t wr_val){
   1392 	return falcon_tsc_wrbl_uc_var (pa, addr, wr_val);
   1393 }
   1394 
   1395 /* Micro RAM Lane Word Write */
   1396 err_code_t falcon_tsc_wrwl_uc_var (const phymod_access_t *pa, uint16_t addr, uint16_t wr_val){
   1397 
   1398 
   1399 	if (addr % 2 != 0)                                                            /* Validate even address */
   1400 		return _error(ERR_CODE_INVALID_RAM_ADDR);
   1401 	if (addr < LANE_VAR_RAM_SIZE)
   1402 		return falcon_tsc_wrw_uc_ram (pa, (LANE_VAR_RAM_BASE + addr + (falcon_tsc_get_lane (pa ) * LANE_VAR_RAM_SIZE)), wr_val); /* Use Micro register interface for writing RAM */
   1403 	else
   1404 		return _error(ERR_CODE_INVALID_RAM_ADDR);
   1405 }
   1406 
   1407 /* Micro RAM Lane Word Signed Write */
   1408 err_code_t falcon_tsc_wrwls_uc_var (const phymod_access_t *pa, uint16_t addr, int16_t wr_val){
   1409 	return falcon_tsc_wrwl_uc_var (pa, addr, wr_val);
   1410 }
   1411 
   1412 
   1413 /************************************************************/
   1414 /*      Serdes IP RAM access - Core RAM Variables           */
   1415 /*----------------------------------------------------------*/
   1416 /*   - through Micro Register Interface for PMD IPs         */
   1417 /*   - through Serdes FW DSC Command Interface for Gallardo */
   1418 /************************************************************/
   1419 
   1420 /* Micro RAM Core Byte Read */
   1421 uint8_t falcon_tsc_rdbc_uc_var (const phymod_access_t *pa, err_code_t *err_code_p, uint8_t addr){
   1422 
   1423 	uint8_t rddata;
   1424 
   1425 	if (!err_code_p)
   1426 		return 0;
   1427 
   1428 	EPSTM(rddata = falcon_tsc_rdb_uc_ram (pa, err_code_p, (CORE_VAR_RAM_BASE + addr)));              /* Use Micro register interface for reading RAM */
   1429 	return rddata;
   1430 }
   1431 
   1432 /* Micro RAM Core Byte Signed Read */
   1433 int8_t falcon_tsc_rdbcs_uc_var (const phymod_access_t *pa, err_code_t *err_code_p, uint8_t addr){
   1434 	return (int8_t)falcon_tsc_rdbc_uc_var (pa, err_code_p, addr);
   1435 }
   1436 
   1437 /* Micro RAM Core Word Read */
   1438 uint16_t falcon_tsc_rdwc_uc_var (const phymod_access_t *pa, err_code_t *err_code_p, uint8_t addr){
   1439 
   1440 	uint16_t rddata;
   1441 
   1442 	if (!err_code_p)
   1443 		return 0;
   1444 	if (addr % 2 != 0) {                                                        /* Validate even address */
   1445 		*err_code_p = ERR_CODE_INVALID_RAM_ADDR;
   1446 		return 0;
   1447 	}
   1448 
   1449 	EPSTM(rddata = falcon_tsc_rdw_uc_ram (pa, err_code_p, (CORE_VAR_RAM_BASE + addr)));          /* Use Micro register interface for reading RAM */
   1450 	return rddata;
   1451 }
   1452 
   1453 /* Micro RAM Core Word Signed Read */
   1454 int16_t falcon_tsc_rdwcs_uc_var (const phymod_access_t *pa, err_code_t *err_code_p, uint8_t addr){
   1455 	return (int16_t)falcon_tsc_rdwc_uc_var (pa, err_code_p, addr);
   1456 }
   1457 
   1458 /* Micro RAM Core Byte Write  */
   1459 err_code_t falcon_tsc_wrbc_uc_var (const phymod_access_t *pa, uint8_t addr, uint8_t wr_val){
   1460 
   1461 
   1462 	if (addr < CORE_VAR_RAM_SIZE)
   1463 		return falcon_tsc_wrb_uc_ram (pa, (CORE_VAR_RAM_BASE + addr), wr_val);                    /* Use Micro register interface for writing RAM */
   1464 	else
   1465 		return _error(ERR_CODE_INVALID_RAM_ADDR);
   1466 }
   1467 
   1468 
   1469 /* Micro RAM Core Byte Signed Write */
   1470 err_code_t falcon_tsc_wrbcs_uc_var (const phymod_access_t *pa, uint8_t addr, int8_t wr_val){
   1471 	return falcon_tsc_wrbc_uc_var (pa, addr, wr_val);
   1472 }
   1473 
   1474 /* Micro RAM Core Word Write  */
   1475 err_code_t falcon_tsc_wrwc_uc_var (const phymod_access_t *pa, uint8_t addr, uint16_t wr_val){
   1476 	if (addr % 2 != 0)                                                            /* Validate even address */
   1477 		return _error(ERR_CODE_INVALID_RAM_ADDR);
   1478 	if (addr < CORE_VAR_RAM_SIZE)
   1479 		return falcon_tsc_wrw_uc_ram (pa, (CORE_VAR_RAM_BASE + addr), wr_val);                         /* Use Micro register interface for writing RAM */
   1480 	else
   1481 		return _error(ERR_CODE_INVALID_RAM_ADDR);
   1482 }
   1483 
   1484 /* Micro RAM Core Word Signed Write */
   1485 err_code_t falcon_tsc_wrwcs_uc_var (const phymod_access_t *pa, uint8_t addr, int16_t wr_val){
   1486 	return falcon_tsc_wrwc_uc_var (pa, addr, wr_val);
   1487 }
   1488 
   1489 
   1490 
   1491 /*******************************************************************/
   1492 /*  APIs to Write Core/Lane Config and User variables into uC RAM  */
   1493 /*******************************************************************/
   1494 
   1495 err_code_t falcon_tsc_set_uc_core_config (const phymod_access_t *pa, struct falcon_tsc_uc_core_config_st struct_val){
   1496 	{
   1497 #ifndef ATE_LOG
   1498 		uint8_t reset_state;
   1499 		ESTM(reset_state = rdc_core_dp_reset_state());
   1500 		if (reset_state < 7) {
   1501 			EFUN_PRINTF(("ERROR: falcon_tsc_set_uc_core_config (pa, ..) called without core_dp_s_rstb=0 Lane=%d reset_state=%d\n", falcon_tsc_get_lane (pa ), reset_state));
   1502 			return _error(ERR_CODE_CORE_DP_NOT_RESET);
   1503 		}
   1504 #endif
   1505 	}
   1506 	if (struct_val.vco_rate_in_Mhz > 0)
   1507 		struct_val.field.vco_rate = MHZ_TO_VCO_RATE(struct_val.vco_rate_in_Mhz);
   1508 	EFUN(_update_uc_core_config_word (pa, &struct_val));
   1509 	EFUN(wrcv_config_word(struct_val.word));
   1510 	return ERR_CODE_NONE;
   1511 }
   1512 
   1513 err_code_t falcon_tsc_set_usr_ctrl_core_event_log_level (const phymod_access_t *pa, uint8_t core_event_log_level){
   1514 	return wrcv_usr_ctrl_core_event_log_level(core_event_log_level);
   1515 }
   1516 
   1517 err_code_t falcon_tsc_set_uc_lane_cfg (const phymod_access_t *pa, struct falcon_tsc_uc_lane_config_st struct_val){
   1518 #ifndef ATE_LOG
   1519 	uint8_t reset_state;
   1520 
   1521 	ESTM(reset_state = rd_lane_dp_reset_state());
   1522 	if (reset_state < 7) {
   1523 		EFUN_PRINTF(("ERROR: falcon_tsc_set_uc_lane_cfg (pa, ..) called without ln_dp_s_rstb=0 Lane=%d reset_state=%d\n", falcon_tsc_get_lane (pa ), reset_state));
   1524 		return _error(ERR_CODE_LANE_DP_NOT_RESET);
   1525 	}
   1526 #endif
   1527 	EFUN(_update_uc_lane_config_word (pa, &struct_val));
   1528 	return wrv_config_word(struct_val.word);
   1529 }
   1530 
   1531 err_code_t falcon_tsc_set_usr_ctrl_lane_event_log_level (const phymod_access_t *pa, uint8_t lane_event_log_level){
   1532 	return wrv_usr_ctrl_lane_event_log_level(lane_event_log_level);
   1533 }
   1534 
   1535 err_code_t falcon_tsc_set_usr_ctrl_disable_startup (const phymod_access_t *pa, struct falcon_tsc_usr_ctrl_disable_functions_st set_val){
   1536 	EFUN(_update_usr_ctrl_disable_functions_byte (pa, &set_val));
   1537 	return wrv_usr_ctrl_disable_startup_functions_word(set_val.word);
   1538 }
   1539 
   1540 err_code_t falcon_tsc_set_usr_ctrl_disable_startup_dfe (const phymod_access_t *pa, struct falcon_tsc_usr_ctrl_disable_dfe_functions_st set_val){
   1541 	EFUN(_update_usr_ctrl_disable_dfe_functions_byte (pa, &set_val));
   1542 	return wrv_usr_ctrl_disable_startup_dfe_functions_byte(set_val.byte);
   1543 }
   1544 
   1545 err_code_t falcon_tsc_set_usr_ctrl_disable_steady_state (const phymod_access_t *pa, struct falcon_tsc_usr_ctrl_disable_functions_st set_val){
   1546     EFUN(_check_uc_lane_stopped(pa));                     /* make sure uC is stopped to avoid race conditions */
   1547 	EFUN(_update_usr_ctrl_disable_functions_byte (pa, &set_val));
   1548 	return wrv_usr_ctrl_disable_steady_state_functions_word(set_val.word);
   1549 }
   1550 
   1551 err_code_t falcon_tsc_set_usr_ctrl_disable_steady_state_dfe (const phymod_access_t *pa, struct falcon_tsc_usr_ctrl_disable_dfe_functions_st set_val){
   1552 	EFUN(_update_usr_ctrl_disable_dfe_functions_byte (pa, &set_val));
   1553 	return wrv_usr_ctrl_disable_steady_state_dfe_functions_byte(set_val.byte);
   1554 }
   1555 
   1556 
   1557 
   1558 /******************************************************************/
   1559 /*  APIs to Read Core/Lane Config and User variables from uC RAM  */
   1560 /******************************************************************/
   1561 
   1562 err_code_t falcon_tsc_get_uc_core_config (const phymod_access_t *pa, struct falcon_tsc_uc_core_config_st *get_val){
   1563 	
   1564 	if (!get_val)
   1565 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1566 	ESTM(get_val->word = rdcv_config_word());
   1567 	EFUN(_update_uc_core_config_st (pa, get_val));
   1568 	return ERR_CODE_NONE;
   1569 }
   1570 
   1571 err_code_t falcon_tsc_get_usr_ctrl_core_event_log_level (const phymod_access_t *pa, uint8_t *core_event_log_level){
   1572 
   1573 	if (!core_event_log_level)
   1574 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1575 
   1576 	ESTM(*core_event_log_level = rdcv_usr_ctrl_core_event_log_level());
   1577 
   1578 	return ERR_CODE_NONE;
   1579 }
   1580 
   1581 err_code_t falcon_tsc_get_uc_lane_cfg (const phymod_access_t *pa, struct falcon_tsc_uc_lane_config_st *get_val){
   1582 
   1583 	if (!get_val)
   1584 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1585 
   1586 	ESTM(get_val->word = rdv_config_word());
   1587 	EFUN(_update_uc_lane_config_st (pa, get_val));
   1588 	return ERR_CODE_NONE;
   1589 }
   1590 
   1591 err_code_t falcon_tsc_get_usr_ctrl_lane_event_log_level (const phymod_access_t *pa, uint8_t *lane_event_log_level){
   1592 
   1593 	if (!lane_event_log_level)
   1594 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1595 
   1596 	ESTM(*lane_event_log_level = rdv_usr_ctrl_lane_event_log_level());
   1597 	return ERR_CODE_NONE;
   1598 }
   1599 
   1600 err_code_t falcon_tsc_get_usr_ctrl_disable_startup (const phymod_access_t *pa, struct falcon_tsc_usr_ctrl_disable_functions_st *get_val){
   1601 
   1602 	if (!get_val)
   1603 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1604 
   1605 	ESTM(get_val->word = rdv_usr_ctrl_disable_startup_functions_word());
   1606 	EFUN(_update_usr_ctrl_disable_functions_st (pa, get_val));
   1607 	return ERR_CODE_NONE;
   1608 }
   1609 
   1610 err_code_t falcon_tsc_get_usr_ctrl_disable_startup_dfe (const phymod_access_t *pa, struct falcon_tsc_usr_ctrl_disable_dfe_functions_st *get_val){
   1611 
   1612 	if (!get_val)
   1613 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1614 
   1615 	ESTM(get_val->byte = rdv_usr_ctrl_disable_startup_dfe_functions_byte());
   1616 	EFUN(_update_usr_ctrl_disable_dfe_functions_st (pa, get_val));
   1617 	return ERR_CODE_NONE;
   1618 }
   1619 
   1620 err_code_t falcon_tsc_get_usr_ctrl_disable_steady_state (const phymod_access_t *pa, struct falcon_tsc_usr_ctrl_disable_functions_st *get_val){
   1621 
   1622 	if (!get_val)
   1623 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1624 
   1625 	ESTM(get_val->word = rdv_usr_ctrl_disable_steady_state_functions_word());
   1626 	EFUN(_update_usr_ctrl_disable_functions_st (pa, get_val));
   1627 	return ERR_CODE_NONE;
   1628 }
   1629 
   1630 err_code_t falcon_tsc_get_usr_ctrl_disable_steady_state_dfe (const phymod_access_t *pa, struct falcon_tsc_usr_ctrl_disable_dfe_functions_st *get_val){
   1631 
   1632 	if (!get_val)
   1633 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1634 
   1635 	ESTM(get_val->byte = rdv_usr_ctrl_disable_steady_state_dfe_functions_byte());
   1636 	EFUN(_update_usr_ctrl_disable_dfe_functions_st (pa, get_val));
   1637 	return ERR_CODE_NONE;
   1638 }
   1639 
   1640 err_code_t falcon_tsc_get_clk90_offset_adjust (const phymod_access_t *pa, int8_t *adjust){
   1641 	if (!adjust)
   1642 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1643 	ESTM(*adjust = (int8_t)rdv_usr_ctrl_clk90_offset_adjust());
   1644 	return ERR_CODE_NONE;
   1645 }
   1646 
   1647 err_code_t falcon_tsc_set_clk90_offset_adjust (const phymod_access_t *pa, int8_t adjust){
   1648 
   1649 	EFUN(_check_uc_lane_stopped (pa ));               /* make sure uC is stopped to a race conditions */
   1650 
   1651 	if ((adjust > 16) || (adjust < -16))
   1652 		return _error(ERR_CODE_INVALID_CLK90_ADJUST);
   1653 	ESTM(wrv_usr_ctrl_clk90_offset_adjust((uint8_t)(adjust)));
   1654 	return ERR_CODE_NONE;
   1655 }
   1656 
   1657 err_code_t falcon_tsc_get_clk90_offset_override (const phymod_access_t *pa, uint8_t *override){
   1658 	if (!override)
   1659 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1660 	ESTM(*override = rdv_usr_ctrl_clk90_offset_override());
   1661 	return ERR_CODE_NONE;
   1662 }
   1663 
   1664 err_code_t falcon_tsc_set_clk90_offset_override (const phymod_access_t *pa, uint8_t enable, uint8_t override){
   1665 
   1666 	EFUN(_check_uc_lane_stopped (pa ));               /* make sure uC is stopped to a race conditions */
   1667 
   1668 	if ((override >= 52) || (override <= 24))
   1669 		return _error(ERR_CODE_INVALID_CLK90_OVERRIDE);
   1670 	ESTM(wrv_usr_ctrl_clk90_offset_override(((enable & 1) << 7) | override));
   1671 	return ERR_CODE_NONE;
   1672 }
   1673 
   1674 err_code_t falcon_tsc_get_clk90_offset (const phymod_access_t *pa, int8_t *offset){
   1675 
   1676 	if (!offset)
   1677 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1678 
   1679 	ESTM(*offset = rdv_usr_sts_phase_hoffset());
   1680 
   1681 	return ERR_CODE_NONE;
   1682 }
   1683 
   1684 
   1685 /******************************************/
   1686 /*  Serdes Register field Poll functions  */
   1687 /******************************************/
   1688 
   1689 #ifndef CUSTOM_REG_POLLING
   1690 
   1691 /* poll for microcontroller to populate the dsc_data register */
   1692 err_code_t falcon_tsc_poll_diag_done (const phymod_access_t *pa, uint16_t *status, uint32_t timeout_ms){
   1693 	uint8_t loop;
   1694 
   1695 	if (!status)
   1696 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1697 
   1698 	for (loop = 0; loop < 100; loop++) {
   1699 		ESTM(*status = rdv_usr_diag_status());
   1700 
   1701 		if ((*status & 0x8000) > 0)
   1702 			return ERR_CODE_NONE;
   1703 		if (loop > 10)
   1704 			EFUN(falcon_tsc_delay_us(10 * timeout_ms));
   1705 	}
   1706 	return _error(ERR_CODE_DIAG_TIMEOUT);
   1707 }
   1708 
   1709 /* poll for microcontroller to populate the dsc_data register */
   1710 err_code_t falcon_tsc_poll_diag_eye_data (const phymod_access_t *pa, uint32_t *data, uint16_t *status, uint32_t timeout_ms){
   1711 	uint8_t loop;
   1712 	uint16_t dscdata;
   1713 
   1714 	if (!data || !status)
   1715 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1716 
   1717 	for (loop = 0; loop < 100; loop++) {
   1718 		ESTM(*status = rdv_usr_diag_status());
   1719 		if (((*status & 0x00FF) > 2) || ((*status & 0x8000) > 0)) {
   1720 			EFUN(falcon_tsc_pmd_uc_cmd (pa,  CMD_READ_DIAG_DATA_WORD, 0, 200));
   1721 			ESTM(dscdata = rd_uc_dsc_data());
   1722 			data[0] = _float8_to_int32 (pa, (float8_t)(dscdata >> 8));
   1723 			data[1] = _float8_to_int32 (pa, (float8_t)(dscdata & 0x00FF));
   1724 			return ERR_CODE_NONE;
   1725 		}
   1726 		if (loop > 10)
   1727 			EFUN(falcon_tsc_delay_us(10 * timeout_ms));
   1728 	}
   1729 	return _error(ERR_CODE_DIAG_TIMEOUT);
   1730 }
   1731 
   1732 /** Poll for field "uc_dsc_ready_for_cmd" = 1 [Return Val => Error_code (0 = Polling Pass)] */
   1733 err_code_t falcon_tsc_poll_uc_dsc_ready_for_cmd_equals_1 (const phymod_access_t *pa, uint32_t timeout_ms){
   1734 #ifndef ATE_LOG
   1735 	uint16_t loop;
   1736 
   1737 	/* read quickly for 4 tries */
   1738 	for (loop = 0; loop < 100; loop++) {
   1739 		uint16_t rddata;
   1740 		EFUN(falcon_tsc_pmd_rdt_reg (pa, DSC_A_DSC_UC_CTRL, &rddata));
   1741 		if (rddata & 0x0080) {          /* bit 7 is uc_dsc_ready_for_cmd */
   1742 			if (rddata & 0x0040) {  /* bit 6 is uc_dsc_error_found   */
   1743 				ESTM_PRINTF(("ERROR : DSC command returned error (after cmd) cmd = 0x%x, supp_info = 0x%02x !\n", rd_uc_dsc_gp_uc_req(), rd_uc_dsc_supp_info()));
   1744                 EFUN(falcon_tsc_pmd_wr_reg(pa, DSC_A_DSC_UC_CTRL,0x80));
   1745                 EFUN(wr_uc_dsc_data(0));
   1746 				return _error(ERR_CODE_UC_CMD_RETURN_ERROR);
   1747 			}
   1748 			return ERR_CODE_NONE;
   1749 		}
   1750 		if (loop > 10)
   1751 			EFUN(falcon_tsc_delay_us(10 * timeout_ms));
   1752 	}
   1753 
   1754 #else
   1755 	{   uint16_t rddata;
   1756 	    EFUN_PRINTF(("// ATE_LOG falcon_tsc_poll_uc_dsc_ready_for_cmd_equals_1 begin\n"));
   1757 	    if (timeout_ms < 100)
   1758 		    EFUN(falcon_tsc_delay_us(1000 * timeout_ms));
   1759 	    else
   1760 		    EFUN(falcon_tsc_delay_ms(timeout_ms));
   1761 	    EFUN(falcon_tsc_pmd_rdt_reg (pa, DSC_A_DSC_UC_CTRL, &rddata));
   1762 	    if (rddata & 0x0080) {              /* bit 7 is uc_dsc_ready_for_cmd */
   1763 		    if (rddata & 0x0040) {      /* bit 6 is uc_dsc_error_found   */
   1764 			    ESTM_PRINTF(("ERROR : DSC command returned error (after cmd) cmd = 0x%x, supp_info = 0x%02x !\n", rd_uc_dsc_gp_uc_req(), rd_uc_dsc_supp_info()));
   1765                 EFUN(falcon_tsc_pmd_wr_reg(pa, DSC_A_DSC_UC_CTRL,0x80));
   1766                 EFUN(wr_uc_dsc_data(0));
   1767 			    return _error(ERR_CODE_UC_CMD_RETURN_ERROR);
   1768 		    }
   1769 		    EFUN_PRINTF(("// ATE_LOG falcon_tsc_poll_uc_dsc_ready_for_cmd_equals_1 end\n"));
   1770 		    return ERR_CODE_NONE;
   1771 	    }
   1772 	    EFUN_PRINTF(("// ATE_LOG falcon_tsc_poll_uc_dsc_ready_for_cmd_equals_1 timeout\n")); }
   1773 #endif
   1774 	EFUN_PRINTF(("ERROR : DSC ready for command is not working, applying workaround and getting debug info !\n"));
   1775 	DISP(rd_uc_dsc_ready_for_cmd());
   1776 	DISP(rd_uc_dsc_supp_info());
   1777 	DISP(rd_uc_dsc_gp_uc_req());
   1778 	DISP(rd_uc_dsc_data());
   1779 	DISP(rd_dsc_state());
   1780 	ESTM_PRINTF(("Uc Core Status Byte = 0x%x\n", rdcv_status_byte()));
   1781 	/* artifically terminate the command to re-enable the command interface */
   1782 	EFUN(wr_uc_dsc_ready_for_cmd(0x1));
   1783 	return _error(ERR_CODE_POLLING_TIMEOUT);      /* Error Code for polling timeout */
   1784 }
   1785 
   1786 /* Poll for field "dsc_state" = DSC_STATE_UC_TUNE [Return Val => Error_code (0 = Polling Pass)] */
   1787 err_code_t falcon_tsc_poll_dsc_state_equals_uc_tune (const phymod_access_t *pa, uint32_t timeout_ms){
   1788 	uint16_t loop;
   1789 	uint16_t dsc_state;
   1790 
   1791 	/* poll 10 times to avoid longer delays later */
   1792 	for (loop = 0; loop < 100; loop++) {
   1793 		ESTM(dsc_state = rd_dsc_state());
   1794 		if (dsc_state == DSC_STATE_UC_TUNE)
   1795 			return ERR_CODE_NONE;
   1796 		if (loop > 10)
   1797 			EFUN(falcon_tsc_delay_us(10 * timeout_ms));
   1798 	}
   1799 	ESTM_PRINTF(("DSC_STATE = %d\n", rd_dsc_state()));
   1800 	return _error(ERR_CODE_POLLING_TIMEOUT);      /* Error Code for polling timeout */
   1801 }
   1802 
   1803 
   1804 
   1805 
   1806 /* Poll for field "micro_ra_initdone" = 1 [Return Val => Error_code (0 = Polling Pass)] */
   1807 err_code_t falcon_tsc_poll_micro_ra_initdone (const phymod_access_t *pa, uint32_t timeout_ms){
   1808 #ifndef ATE_LOG
   1809 	uint16_t loop;
   1810 
   1811 	uint8_t result;
   1812 
   1813 	for (loop = 0; loop <= 100; loop++) {
   1814 		ESTM(result = rdc_micro_ra_initdone());
   1815 		if (result)
   1816 			return ERR_CODE_NONE;
   1817 		EFUN(falcon_tsc_delay_us(10 * timeout_ms));
   1818 	}
   1819 	return _error(ERR_CODE_POLLING_TIMEOUT);      /* Error Code for polling timeout */
   1820 #else
   1821     EFUN(falcon_tsc_delay_ms(timeout_ms));
   1822     return (ERR_CODE_NONE);
   1823 #endif /* ATE_LOG */
   1824 }
   1825 #endif /* CUSTOM_REG_POLLING */
   1826 
   1827 
   1828 
   1829 
   1830 err_code_t falcon_tsc_init_pram_for_uc_load (const phymod_access_t *pa, uint16_t ucode_len){
   1831 
   1832 	if (ucode_len > UCODE_MAX_SIZE)                   /* uCode size should be less than UCODE_MAX_SIZE  */
   1833 		return _error(ERR_CODE_INVALID_UCODE_LEN);
   1834 
   1835 	EFUN(wrc_micro_master_clk_en(0x1));                     /* Enable clock to microcontroller subsystem */
   1836 	EFUN(wrc_micro_master_rstb(0x1));                       /* De-assert reset to microcontroller sybsystem */
   1837 	EFUN(wrc_micro_master_rstb(0x0));                       /* Assert reset to microcontroller sybsystem - Toggling reset*/
   1838 	EFUN(wrc_micro_master_rstb(0x1));                       /* De-assert reset to microcontroller sybsystem */
   1839 
   1840 	EFUN(wrc_micro_ra_init(0x1));                           /* Set initialization command to initialize code RAM */
   1841 	EFUN(falcon_tsc_poll_micro_ra_initdone (pa, 250));           /* Poll for micro_ra_initdone = 1 to indicate initialization done */
   1842 
   1843 	EFUN(wrc_micro_ra_init(0x0));                           /* Clear initialization command */
   1844 	/* ucode_len_padded = ((ucode_len + 3) & 0xFFFC); */    /* make sure it is on 32bit boundary */
   1845 	EFUN(wrc_micro_pramif_ahb_wraddr_msw(0x0000));
   1846 	EFUN(wrc_micro_pramif_ahb_wraddr_lsw(0x0000));
   1847 	EFUN(wrc_micro_pram_if_rstb(1));
   1848 	EFUN(wrc_micro_pramif_en(1));
   1849 
   1850 	/* Wait 8 pram clocks */
   1851 	/* write ucode into pram */
   1852 	/* Wait 8 pram clocks */
   1853 	/* call falcon_tsc_finish_pram_load */
   1854 	return ERR_CODE_NONE;
   1855 }
   1856 
   1857 err_code_t falcon_tsc_finish_pram_load (const phymod_access_t *pa){
   1858 	EFUN(wrc_micro_pramif_en(0));
   1859 	EFUN(wrc_micro_core_clk_en(1));
   1860 	/* EFUN(wrc_micro_core_rstb(1)); */
   1861 	return ERR_CODE_NONE;
   1862 }
   1863 
   1864 
   1865 /****************************************/
   1866 /*  Serdes Register/Variable Dump APIs  */
   1867 /****************************************/
   1868 
   1869 err_code_t falcon_tsc_reg_dump (const phymod_access_t *pa){
   1870 
   1871 	uint16_t addr, rddata;
   1872 
   1873 	EFUN_PRINTF(("\n****  SERDES REGISTER DUMP    ****"));
   1874 
   1875 	for (addr = 0x0; addr < 0x10; addr++) {
   1876 		if (!(addr % 16))
   1877 			EFUN_PRINTF(("\n%04x ", addr));
   1878 		EFUN(falcon_tsc_pmd_rdt_reg (pa, addr, &rddata));
   1879 		EFUN_PRINTF(("%04x ", rddata));
   1880 	}
   1881 
   1882 	for (addr = 0x90; addr < 0xA0; addr++) {
   1883 		if (!(addr % 16))
   1884 			EFUN_PRINTF(("\n%04x ", addr));
   1885 		EFUN(falcon_tsc_pmd_rdt_reg (pa, addr, &rddata));
   1886 		EFUN_PRINTF(("%04x ", rddata));
   1887 	}
   1888 
   1889 	for (addr = 0xD000; addr < 0xD180; addr++) {
   1890 		if (!(addr % 16))
   1891 			EFUN_PRINTF(("\n%04x ", addr));
   1892 		EFUN(falcon_tsc_pmd_rdt_reg (pa, addr, &rddata));
   1893 		EFUN_PRINTF(("%04x ", rddata));
   1894 	}
   1895 
   1896 
   1897 
   1898 	for (addr = 0xD200; addr < 0xD230; addr++) {
   1899 		if (!(addr % 16))
   1900 			EFUN_PRINTF(("\n%04x ", addr));
   1901 		EFUN(falcon_tsc_pmd_rdt_reg (pa, addr, &rddata));
   1902 		EFUN_PRINTF(("%04x ", rddata));
   1903 	}
   1904 
   1905 	for (addr = 0xFFD0; addr < 0xFFE0; addr++) {
   1906 		if (!(addr % 16))
   1907 			EFUN_PRINTF(("\n%04x ", addr));
   1908 		EFUN(falcon_tsc_pmd_rdt_reg (pa, addr, &rddata));
   1909 		EFUN_PRINTF(("%04x ", rddata));
   1910 	}
   1911 	return ERR_CODE_NONE;
   1912 }
   1913 
   1914 
   1915 err_code_t falcon_tsc_uc_core_var_dump (const phymod_access_t *pa){
   1916 	uint8_t addr;
   1917 
   1918 	EFUN_PRINTF(("\n**** SERDES UC CORE RAM VARIABLE DUMP ****"));
   1919 
   1920 	for (addr = 0x0; addr < CORE_VAR_RAM_SIZE; addr++) {
   1921 		if (!(addr % 26))
   1922 			EFUN_PRINTF(("\n%04x ", addr));
   1923 		ESTM_PRINTF(("%02x ", falcon_tsc_rdbc_uc_var (pa, __ERR, addr)));
   1924 	}
   1925 	return ERR_CODE_NONE;
   1926 }
   1927 
   1928 
   1929 err_code_t falcon_tsc_uc_lane_var_dump (const phymod_access_t *pa){
   1930 	uint8_t rx_lock, uc_stopped = 0;
   1931 	uint16_t addr;
   1932 
   1933 
   1934 	EFUN_PRINTF(("\n**** SERDES UC LANE %d RAM VARIABLE DUMP ****", falcon_tsc_get_lane (pa )));
   1935 
   1936 	ESTM(rx_lock = rd_pmd_rx_lock());
   1937 
   1938 	if (rx_lock == 1) {
   1939 		ESTM(uc_stopped = rdv_usr_sts_micro_stopped());
   1940 		if (!uc_stopped)
   1941 			EFUN(falcon_tsc_stop_rx_adaptation (pa, 1));
   1942 	} else
   1943 		EFUN(falcon_tsc_pmd_uc_control (pa, CMD_UC_CTRL_STOP_IMMEDIATE, 200));
   1944 
   1945 	for (addr = 0x0; addr < LANE_VAR_RAM_SIZE; addr++) {
   1946 		if (!(addr % 26))
   1947 			EFUN_PRINTF(("\n%04x ", addr));
   1948 		ESTM_PRINTF(("%02x ", falcon_tsc_rdbl_uc_var (pa, __ERR, addr)));
   1949 	}
   1950 
   1951 	if (rx_lock == 1) {
   1952 		if (!uc_stopped)
   1953 			EFUN(falcon_tsc_stop_rx_adaptation (pa, 0));
   1954 	} else
   1955 		EFUN(falcon_tsc_stop_rx_adaptation (pa, 0));
   1956 
   1957 	return ERR_CODE_NONE;
   1958 }
   1959 
   1960 /* Required Diagnostic Functions */
   1961 err_code_t falcon_tsc_display_diag_data (const phymod_access_t *pa, int32_t diag_level){
   1962 	uint8_t rx_lock, micro_stop;
   1963 	uint32_t api_version;
   1964 
   1965 	EFUN_PRINTF(("\n**** SERDES DISPLAY DIAG DATA ****\n"));
   1966 	ESTM_PRINTF(("Rev ID Letter  = %02X\n", rdc_revid_rev_letter()));
   1967 	ESTM_PRINTF(("Rev ID Process = %02X\n", rdc_revid_process()));
   1968 	ESTM_PRINTF(("Rev ID Model   = %02X\n", rdc_revid_model()));
   1969 	ESTM_PRINTF(("Rev ID Model   = %02X\n", rdc_revid2()));
   1970 	ESTM_PRINTF(("Rev ID # Lanes = %d\n", rdc_revid_multiplicity()));
   1971 	ESTM_PRINTF(("Core = %d; LANE = %d\n", falcon_tsc_get_core(), falcon_tsc_get_lane (pa )));
   1972 	EFUN(falcon_tsc_version (pa, &api_version));
   1973 	EFUN_PRINTF(("SERDES API Version         = %06X\n", api_version));
   1974 	ESTM_PRINTF(("Common Ucode Version       = %04X", rdcv_common_ucode_version()));
   1975 	ESTM_PRINTF(("_%02X\n", rdcv_common_ucode_minor_version()));
   1976 	ESTM_PRINTF(("AFE Hardware Version       = 0x%X\n\n", rdcv_afe_hardware_version()));
   1977 
   1978 
   1979 	/* stop micro so all accesses are consistent */
   1980 	ESTM(rx_lock = rd_pmd_rx_lock());
   1981 	ESTM(micro_stop = rdv_usr_sts_micro_stopped());
   1982 	if (rx_lock == 1) {
   1983 		if (!micro_stop)
   1984 			EFUN(falcon_tsc_stop_rx_adaptation (pa, 1));
   1985 	} else
   1986 		EFUN(falcon_tsc_pmd_uc_control (pa, CMD_UC_CTRL_STOP_IMMEDIATE, 200));
   1987 
   1988 	if (diag_level & SRDS_DIAG_LANE) {
   1989 		struct falcon_tsc_detailed_lane_status_st lane_st;
   1990 		USR_MEMSET(&lane_st, 0, sizeof(lane_st));
   1991 		EFUN(falcon_tsc_log_full_pmd_state (pa, &lane_st));
   1992 		EFUN(falcon_tsc_disp_full_pmd_state (pa, &lane_st, 1));
   1993 	} else {
   1994 		EFUN(falcon_tsc_display_lane_state_hdr (pa ));
   1995 		EFUN(falcon_tsc_display_lane_state (pa ));
   1996 	}
   1997 	if (diag_level & SRDS_DIAG_CORE) {
   1998 		EFUN(falcon_tsc_display_core_state_hdr (pa ));
   1999 		EFUN(falcon_tsc_display_core_state_line (pa ));
   2000 	}
   2001 	if (diag_level & SRDS_DIAG_EVENT) {
   2002 		uint8_t trace_mem[1000]; 
   2003 		USR_MEMSET(trace_mem, 0, sizeof(trace_mem));
   2004 		EFUN(falcon_tsc_read_event_log (pa, trace_mem, EVENT_LOG_HEX));
   2005 	}
   2006 	if (diag_level & SRDS_DIAG_EYE)
   2007 		EFUN(falcon_tsc_display_eye_scan (pa ));
   2008 	if (diag_level & SRDS_DIAG_REG_CORE)
   2009 		EFUN(falcon_tsc_reg_dump (pa ));
   2010 	/* currently REG_CORE and REG_LANE dump same data. */
   2011 	/*if(diag_level & SRDS_DIAG_REG_LANE) {*/
   2012 	/*    EFUN(falcon_tsc_reg_dump (pa ));*/
   2013 	/*}*/
   2014 	if (diag_level & SRDS_DIAG_UC_CORE)
   2015 		EFUN(falcon_tsc_uc_core_var_dump (pa ));
   2016 	if (diag_level & SRDS_DIAG_UC_LANE)
   2017 		EFUN(falcon_tsc_uc_lane_var_dump (pa ));
   2018 	if (diag_level & SRDS_DIAG_LANE_DEBUG)
   2019 		EFUN(falcon_tsc_display_lane_debug_status (pa ));
   2020 	if (diag_level & SRDS_DIAG_BER_VERT) {
   2021 		/* display ber projections for all channels */
   2022 		uint8_t ber_mode = DIAG_BER_VERT | DIAG_BER_POS;
   2023 		uint8_t timer_control = 23;             /* 30 seconds */
   2024 		uint8_t err_threshold = 100 / 16;       /* 100 errors */
   2025 		EFUN(_falcon_tsc_display_ber_scan_data (pa, ber_mode, timer_control,  err_threshold));
   2026 		ber_mode = DIAG_BER_VERT | DIAG_BER_NEG;
   2027 		EFUN(_falcon_tsc_display_ber_scan_data (pa, ber_mode, timer_control,  err_threshold));
   2028 	}
   2029 	if (diag_level & SRDS_DIAG_BER_HORZ) {
   2030 		/* display ber projections for all channels */
   2031 		uint8_t ber_mode = DIAG_BER_HORZ | DIAG_BER_POS;
   2032 		uint8_t timer_control = 23;             /* 30 seconds */
   2033 		uint8_t err_threshold = 100 / 16;       /* 100 errors */
   2034 		EFUN(_falcon_tsc_display_ber_scan_data (pa, ber_mode, timer_control,  err_threshold));
   2035 		ber_mode = DIAG_BER_HORZ | DIAG_BER_NEG;
   2036 		EFUN(_falcon_tsc_display_ber_scan_data (pa, ber_mode, timer_control,  err_threshold));
   2037 	}
   2038 
   2039 	/* re enable micro */
   2040 	if (rx_lock == 1) {
   2041 		if (!micro_stop)
   2042 			EFUN(falcon_tsc_stop_rx_adaptation (pa, 0));
   2043 	} else
   2044 		EFUN(falcon_tsc_stop_rx_adaptation (pa, 0));
   2045 
   2046 	EFUN_PRINTF(("\n\n"));
   2047 	return ERR_CODE_NONE;
   2048 
   2049 }
   2050 
   2051 /* Required Diagnostic Functions */
   2052 err_code_t falcon_tsc_diag_access (const phymod_access_t *pa, enum srds_diag_access_enum type, uint16_t addr, uint16_t data, uint16_t param){
   2053 
   2054 	switch (type) {
   2055 	case SRDS_REG_READ:      {
   2056 		uint16_t tmp;
   2057 		if (data > 1) {
   2058 			uint16_t i;
   2059 			EFUN_PRINTF(("\n****  SERDES BLK REGISTER READ    ****"));
   2060 			for (i = 0; i < data; i++) {
   2061 				if (!(i % 16))
   2062 					ESTM_PRINTF(("\n%04x ", i + addr));
   2063 				EFUN(falcon_tsc_pmd_rdt_reg (pa, i + addr, &tmp));
   2064 				ESTM_PRINTF(("%04x ", tmp));
   2065 			}
   2066 			EFUN_PRINTF(("\n"));
   2067 		} else {
   2068 			EFUN(falcon_tsc_pmd_rdt_reg (pa, addr, &tmp));
   2069 			EFUN_PRINTF(("Register Read: x%04x = x%04x\n", addr, tmp));
   2070 		}
   2071 	} break;
   2072 	case SRDS_REG_RMW:       {
   2073 		uint16_t tmp, tmp2;
   2074 		EFUN(falcon_tsc_pmd_rdt_reg (pa, addr, &tmp));
   2075 		tmp2 = (tmp & ~param) | (param & data);
   2076 		EFUN(falcon_tsc_pmd_wr_reg (pa, addr, tmp2));
   2077 		EFUN_PRINTF(("Register RMW: x%04x = x%04x -> x%04x\n", addr, tmp, tmp2));
   2078 	} break;
   2079 	case SRDS_CORE_RAM_READ_BYTE: {
   2080 		if (data > 1) {
   2081 			uint8_t i;
   2082 			EFUN_PRINTF(("\n****  SERDES BLK CORE RAM READ BYTE   ****"));
   2083 			for (i = 0; i < (uint8_t)data; i++) {
   2084 				if (!(i % 26))
   2085 					ESTM_PRINTF(("\n%04x ", i + (uint8_t)addr));
   2086 				ESTM_PRINTF(("%02x ", falcon_tsc_rdbc_uc_var (pa, __ERR, i + (uint8_t)addr)));
   2087 			}
   2088 			EFUN_PRINTF(("\n"));
   2089 		} else
   2090 			ESTM_PRINTF(("Core RAM Read byte: x%04x = x%02x\n", (uint8_t)addr, falcon_tsc_rdbc_uc_var (pa, __ERR, (uint8_t)addr)));
   2091 	} break;
   2092 	case SRDS_LANE_RAM_READ_BYTE: {
   2093 		if (data > 1) {
   2094 			uint16_t i;
   2095 			EFUN_PRINTF(("\n****  SERDES BLK LANE RAM READ BYTE   ****"));
   2096 			for (i = 0; i < data; i++) {
   2097 				if (!(i % 26))
   2098 					ESTM_PRINTF(("\n%04x ", i + addr));
   2099 				ESTM_PRINTF(("%02x ", falcon_tsc_rdbl_uc_var (pa, __ERR, i + addr)));
   2100 			}
   2101 			EFUN_PRINTF(("\n"));
   2102 		} else
   2103 			ESTM_PRINTF(("Lane RAM Read byte: x%04x = x%02x\n", addr, falcon_tsc_rdbl_uc_var (pa, __ERR, addr)));
   2104 	} break;
   2105 	case SRDS_CORE_RAM_READ_WORD: {
   2106 		if (data > 1) {
   2107 			uint8_t i;
   2108 			EFUN_PRINTF(("\n****  SERDES BLK CORE RAM READ WORD   ****"));
   2109 			for (i = 0; i < (uint8_t)data; i += 2) {
   2110 				if (!(i % 16))
   2111 					ESTM_PRINTF(("\n%04x ", i + (uint8_t)addr));
   2112 				ESTM_PRINTF(("%04x ", falcon_tsc_rdwc_uc_var (pa, __ERR, i + (uint8_t)addr)));
   2113 			}
   2114 			EFUN_PRINTF(("\n"));
   2115 		} else
   2116 			ESTM_PRINTF(("Core RAM Read word: x%04x = x%04x\n", addr, falcon_tsc_rdwc_uc_var (pa, __ERR, (uint8_t)addr)));
   2117 	} break;
   2118 	case SRDS_LANE_RAM_READ_WORD: {
   2119 		if (data > 1) {
   2120 			uint16_t i;
   2121 			EFUN_PRINTF(("\n****  SERDES BLK LANE RAM READ WORD   ****"));
   2122 			for (i = 0; i < data; i += 2) {
   2123 				if (!(i % 16))
   2124 					ESTM_PRINTF(("\n%04x ", i = i + addr));
   2125 				ESTM_PRINTF(("%04x ", falcon_tsc_rdwl_uc_var (pa, __ERR, i + addr)));
   2126 			}
   2127 			EFUN_PRINTF(("\n"));
   2128 		} else
   2129 			ESTM_PRINTF(("Lane RAM Read word: x%04x = x%04x\n", addr, falcon_tsc_rdwl_uc_var (pa, __ERR, addr)));
   2130 	} break;
   2131 	case SRDS_CORE_RAM_RMW_BYTE:  {
   2132 		uint8_t tmp, tmp2;
   2133 		ESTM(tmp = falcon_tsc_rdbc_uc_var (pa, __ERR, (uint8_t)addr));
   2134 		tmp2 = (tmp & (uint8_t) ~param) | ((uint8_t)param & data);
   2135 		EFUN(falcon_tsc_wrbc_uc_var (pa, (uint8_t)addr, tmp2));
   2136 		EFUN_PRINTF(("Core RAM RMW byte: x%04x = x%02x -> x%02x\n", addr, tmp, tmp2));
   2137 	} break;
   2138 	case SRDS_LANE_RAM_RMW_BYTE:  {
   2139 		uint8_t tmp, tmp2;
   2140 		ESTM(tmp = falcon_tsc_rdbl_uc_var (pa, __ERR, addr));
   2141 		tmp2 = (tmp & (uint8_t) ~param) | ((uint8_t)param & data);
   2142 		EFUN(falcon_tsc_wrbl_uc_var (pa, addr, tmp2));
   2143 		EFUN_PRINTF(("Lane RAM RMW byte: x%04x = x%02x -> x%02x\n", addr, tmp, tmp2));
   2144 	} break;
   2145 	case SRDS_CORE_RAM_RMW_WORD:  {
   2146 		uint16_t tmp, tmp2;
   2147 		ESTM(tmp = falcon_tsc_rdwc_uc_var (pa, __ERR, (uint8_t)addr));
   2148 		tmp2 = (tmp & ~param) | (param & data);
   2149 		EFUN(falcon_tsc_wrwc_uc_var (pa, (uint8_t)addr, tmp2));
   2150 		EFUN_PRINTF(("Core RAM RMW word: x%04x = x%04x -> x%04x\n", addr, tmp, tmp2));
   2151 	} break;
   2152 	case SRDS_LANE_RAM_RMW_WORD:  {
   2153 		uint16_t tmp, tmp2;
   2154 		ESTM(tmp = falcon_tsc_rdwl_uc_var (pa, __ERR, addr));
   2155 		tmp2 = (tmp & ~param) | (param & data);
   2156 		EFUN(falcon_tsc_wrwl_uc_var (pa, addr, tmp2));
   2157 		EFUN_PRINTF(("Lane RAM RMW word: x%04x = x%04x -> x%04x\n", addr, tmp, tmp2));
   2158 	} break;
   2159 	case SRDS_GLOB_RAM_READ_BYTE: {
   2160 		if (data > 1) {
   2161 			uint16_t i;
   2162 			EFUN_PRINTF(("\n****  SERDES BLK GLOB RAM READ BYTE   ****"));
   2163 			for (i = 0; i < data; i++) {
   2164 				if (!(i % 16))
   2165 					ESTM_PRINTF(("\n%04x ", i + addr));
   2166 				ESTM_PRINTF(("%02x ", _falcon_tsc_rdb_uc_var (pa, __ERR, i + addr)));
   2167 			}
   2168 			EFUN_PRINTF(("\n"));
   2169 		} else
   2170 			ESTM_PRINTF(("Glob RAM Read byte: x%04x = x%02x\n", addr, _falcon_tsc_rdb_uc_var (pa, __ERR, addr)));
   2171 	} break;
   2172 	case SRDS_GLOB_RAM_RMW_BYTE:  {
   2173 		uint8_t tmp, tmp2;
   2174 		ESTM(tmp = _falcon_tsc_rdb_uc_var (pa, __ERR, addr));
   2175 		tmp2 = (tmp & (uint8_t) ~param) | ((uint8_t)param & data);
   2176 		EFUN(_falcon_tsc_wrb_uc_var (pa, addr, tmp2));
   2177 		EFUN_PRINTF(("Glob RAM RMW byte: x%04x = x%02x -> x%02x\n", addr, tmp, tmp2));
   2178 	} break;
   2179 	case SRDS_GLOB_RAM_READ_WORD: {
   2180 		if (data > 1) {
   2181 			uint16_t i;
   2182 			EFUN_PRINTF(("\n****  SERDES BLK GLOB RAM READ WORD   ****"));
   2183 			for (i = 0; i < data; i += 2) {
   2184 				if (!(i % 16))
   2185 					ESTM_PRINTF(("\n%04x ", i + addr));
   2186 				ESTM_PRINTF(("%04x ", _falcon_tsc_rdw_uc_var (pa, __ERR, i + addr)));
   2187 			}
   2188 			EFUN_PRINTF(("\n"));
   2189 		} else
   2190 			ESTM_PRINTF(("Glob RAM Read word: x%04x = x%04x\n", addr, _falcon_tsc_rdw_uc_var (pa, __ERR, addr)));
   2191 	} break;
   2192 	case SRDS_GLOB_RAM_RMW_WORD:  {
   2193 		uint16_t tmp, tmp2;
   2194 		ESTM(tmp = _falcon_tsc_rdw_uc_var (pa, __ERR, addr));
   2195 		tmp2 = (tmp & ~param) | (param & data);
   2196 		EFUN(_falcon_tsc_wrw_uc_var (pa, addr, tmp2));
   2197 		EFUN_PRINTF(("Glob RAM RMW word: x%04x = x%04x -> x%04x\n", addr, tmp, tmp2));
   2198 	} break;
   2199 	case SRDS_UC_CMD:        {
   2200 		uint16_t tmp;
   2201 		EFUN(falcon_tsc_pmd_uc_cmd_with_data (pa, (enum srds_pmd_uc_cmd_enum)addr, (uint8_t)param, data, 100));
   2202 		ESTM(tmp = rd_uc_dsc_data());
   2203 		EFUN_PRINTF(("uC Command: cmd=x%02x supp=x%02x data=x%04x returned=x%04x\n", addr, param, data, tmp));
   2204 	} break;
   2205 	case SRDS_BER_PROJ_DATA: {
   2206 		/* display ber projections for all channels */
   2207 		EFUN(_falcon_tsc_display_ber_scan_data (pa, (uint8_t)addr, (uint8_t)data,  (uint8_t)(param >> 4)));
   2208 	} break;
   2209 	case SRDS_EN_BREAKPOINT: 
   2210 	case SRDS_GOTO_BREAKPOINT:
   2211 	case SRDS_RD_BREAKPOINT:
   2212 	case SRDS_DIS_BREAKPOINT:
   2213 	default: EFUN_PRINTF(("Invalid request type falcon_tsc_diag_access\n"));
   2214 	}
   2215 
   2216 	return ERR_CODE_NONE;
   2217 }
   2218 
   2219 /************************/
   2220 /*  Serdes API Version  */
   2221 /************************/
   2222 
   2223 err_code_t falcon_tsc_version (const phymod_access_t *pa, uint32_t *api_version){
   2224 
   2225 	if (!api_version)
   2226 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   2227     *api_version = 0xA1021F;
   2228 	return ERR_CODE_NONE;
   2229 }
   2230 
   2231 
   2232 /***************************************/
   2233 /*  API Function to Read Event Logger  */
   2234 /***************************************/
   2235 
   2236 err_code_t falcon_tsc_read_event_log (const phymod_access_t *pa, uint8_t *trace_mem, enum srds_event_log_display_mode_enum display_mode){
   2237 
   2238 	/* validate input arguments */
   2239 	if (trace_mem == NULL || (display_mode >= EVENT_LOG_MODE_MAX))
   2240 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   2241 
   2242 	/* stop writing event log */
   2243 	EFUN(falcon_tsc_event_log_stop (pa ));
   2244 
   2245 	EFUN(falcon_tsc_event_log_readmem (pa, trace_mem));
   2246 
   2247 	EFUN(falcon_tsc_event_log_display (pa, trace_mem, display_mode));
   2248 
   2249 	return ERR_CODE_NONE;
   2250 }
   2251 
   2252 err_code_t falcon_tsc_event_log_stop (const phymod_access_t *pa){
   2253 
   2254 
   2255 	EFUN_PRINTF(("\n\n********************************************\n"));
   2256 	EFUN_PRINTF((    "**** SERDES UC TRACE MEMORY DUMP ***********\n"));
   2257 	EFUN_PRINTF((    "********************************************\n"));
   2258 
   2259 	/* Start Read to stop uC logging and read the word at last event written by uC */
   2260 	EFUN(falcon_tsc_pmd_uc_cmd (pa, CMD_EVENT_LOG_READ, CMD_EVENT_LOG_READ_START, 1000));
   2261 
   2262 	return ERR_CODE_NONE;
   2263 }
   2264 
   2265 err_code_t falcon_tsc_event_log_readmem (const phymod_access_t *pa, uint8_t *trace_mem){
   2266 	uint8_t uc_dsc_supp_info;
   2267 	uint16_t addr = 0, trace_mem_size = 0;
   2268 
   2269 	/* validate input arguments */
   2270 	if (trace_mem == NULL) return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   2271 
   2272 	ESTM_PRINTF(( "\n  DEBUG INFO: trace memory read index = 0x%04x\n", rdcv_trace_mem_rd_idx()));
   2273 
   2274 	trace_mem_size = 768;
   2275 	EFUN_PRINTF(("  DEBUG INFO: trace memory size = 0x%04x\n\n", trace_mem_size));
   2276 
   2277 	do {
   2278 		/* Read Next */
   2279 		EFUN(falcon_tsc_pmd_uc_cmd (pa, CMD_EVENT_LOG_READ, CMD_EVENT_LOG_READ_NEXT, 1000));
   2280 
   2281 		if (addr >= trace_mem_size)
   2282 			return ERR_CODE_INVALID_EVENT_LOG_READ;
   2283 		else
   2284 			addr++;
   2285 
   2286 		ESTM(*(trace_mem++) = (uint8_t)rd_uc_dsc_data());
   2287 		ESTM(uc_dsc_supp_info = rd_uc_dsc_supp_info());
   2288 	} while (uc_dsc_supp_info != 1);
   2289 
   2290 	/* Read Done to resume logging  */
   2291 	EFUN(falcon_tsc_pmd_uc_cmd (pa, CMD_EVENT_LOG_READ, CMD_EVENT_LOG_READ_DONE, 1000));
   2292 
   2293 	return ERR_CODE_NONE;
   2294 }
   2295 
   2296 err_code_t falcon_tsc_event_log_display (const phymod_access_t *pa, uint8_t *trace_mem, enum srds_event_log_display_mode_enum display_mode){
   2297 #define MAX_ENTRY_SIZE   (7)
   2298 #define NOR_ENTRY_SIZE   (4)
   2299 	uint16_t trace_mem_size = 0;
   2300 	uint8_t num_lanes = 0;
   2301 	uint8_t is_ref_time_found = 0, is_last_event_timewrap = 0;
   2302 	uint8_t post_cursor = 0, curr_cursor = 0, prev_cursor = 0;
   2303 	uint16_t addr = 0, rr = 0, prev_rr = 0;
   2304 	uint8_t cc = 0;
   2305 	uint16_t time = 0, ref_time = 0, num_time_wraparound = 0, this_num_time_wraparound = 0;
   2306 	USR_DOUBLE prev_time = 0, curr_time = 0;
   2307 	uint8_t word_per_row = 8;
   2308 	uint8_t prev_event = 0;
   2309 	uint8_t supp_info[MAX_ENTRY_SIZE - NOR_ENTRY_SIZE];
   2310 	char uc_lane_id_str[256];
   2311 	uint8_t char_0 = '0';
   2312 
   2313 	/* validate input arguments */
   2314 	if (trace_mem == NULL || (display_mode >= EVENT_LOG_MODE_MAX))
   2315 		return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   2316 
   2317 	trace_mem_size = 768;
   2318 	num_lanes = 4;
   2319 
   2320 	/* output */
   2321 	if (display_mode == EVENT_LOG_HEX || display_mode == EVENT_LOG_HEX_AND_DECODED) {
   2322 		/* print the 16-bit words in Hex format to screen, 8 words per row */
   2323 		for (rr = 0; rr < trace_mem_size; rr += (2 * word_per_row)) {
   2324 			for (cc = 0; cc < 2 * word_per_row; cc += 2)
   2325 				EFUN_PRINTF(("  0x%02x%02x", *(trace_mem + rr + cc), *(trace_mem + rr + cc + 1)));
   2326 			EFUN_PRINTF(("    %d\n", rr));
   2327 		}
   2328 	}
   2329 	if (display_mode == EVENT_LOG_DECODED || display_mode == EVENT_LOG_HEX_AND_DECODED) {
   2330 		/* decode for level 1 events */
   2331 
   2332 		/* print a text log of the events going backwards in time, showing time as T-10.340ms, where T is when the Start Read happened. */
   2333 		addr = 0;
   2334 		while (addr < trace_mem_size - 8) {                                                     /* last 8-byte reserved for trace memory wraparound */
   2335 
   2336 			if (*(trace_mem + addr) == 0x0) {                                               /* reach event log end */
   2337 				EFUN_PRINTF(("\n========== End of Event Log ==================\n"));
   2338 				break;
   2339 			}
   2340 
   2341 			if (*(trace_mem + addr) == 0xff) {                                           /* timestamp wraparound event handling */
   2342 
   2343 				this_num_time_wraparound = *(trace_mem + (++addr));
   2344 				this_num_time_wraparound = ((this_num_time_wraparound << 8) | *(trace_mem + (++addr)));
   2345 				num_time_wraparound += this_num_time_wraparound;
   2346 
   2347 				if (!is_last_event_timewrap) {                                         /* display the rest of previous event info */
   2348 					EFUN_PRINTF((","));
   2349 					EFUN(_display_event (pa, prev_event, (uint8_t)prev_rr, prev_cursor, curr_cursor, post_cursor, supp_info));
   2350 					is_last_event_timewrap = 1;
   2351 				}
   2352 
   2353 				EFUN_PRINTF(("\n  %5d timestamp wraparound(s). \n\n", this_num_time_wraparound));
   2354 				this_num_time_wraparound = 0;
   2355 
   2356 				addr++;
   2357 				continue;
   2358 			}else  {
   2359 				cc = (trace_mem[addr] & 0x1f);                                         /* lane id */
   2360 				if (cc >= num_lanes) {
   2361 					EFUN_PRINTF(("\n\n  Incorrect lane ID. Terminating event log display for current core... \n\n"));
   2362 					break;
   2363 				}
   2364 
   2365 				rr = (uint16_t)((trace_mem[addr] >> 5) & 0x7);                          /* determine event entry length */
   2366 
   2367 				time = *(trace_mem + (++addr));                                         /* timestamp */
   2368 				time = ((time << 8) | *(trace_mem + (++addr)));
   2369 				if (is_ref_time_found == 0) {                                           /* determine the reference time origin */
   2370 					is_ref_time_found = 1;
   2371 					ref_time = time;
   2372 				}else  {
   2373 #ifdef SERDES_API_FLOATING_POINT
   2374 					curr_time = (time - ref_time - (num_time_wraparound * 65536)) / 100.0;
   2375 #else
   2376 					curr_time = (time - ref_time - (num_time_wraparound * 65536)) / 100;
   2377 #endif
   2378 					if (!is_last_event_timewrap) {
   2379 #ifdef SERDES_API_FLOATING_POINT
   2380 						EFUN_PRINTF((" (+%.2f),", prev_time - curr_time));
   2381 #else
   2382 						EFUN_PRINTF((" (+%d),", prev_time - curr_time));
   2383 #endif
   2384 						EFUN(_display_event (pa, prev_event, (uint8_t)prev_rr, prev_cursor, curr_cursor, post_cursor, supp_info));
   2385 					}else
   2386 						is_last_event_timewrap = 0;
   2387 				}
   2388 
   2389                 /* coverity[dead_error_condition] */
   2390 				if (cc < 10) {
   2391 					uc_lane_id_str[0] = char_0 + cc;
   2392 					uc_lane_id_str[1] = '\0';
   2393                     /* coverity[dead_error_line] */
   2394 				} else if (cc < 100) {
   2395 					uc_lane_id_str[0] = char_0 + (cc / 10);
   2396 					uc_lane_id_str[1] = char_0 + (cc % 10);
   2397 					uc_lane_id_str[2] = '\0';
   2398                     /* coverity[dead_error_line] */
   2399 				} else {
   2400 					uc_lane_id_str[0] = char_0 + (cc / 100);
   2401 					uc_lane_id_str[1] = char_0 + ((cc % 100) - (cc % 10)) / 10;
   2402 					uc_lane_id_str[2] = char_0 + (cc % 10);
   2403 					uc_lane_id_str[3] = '\0';
   2404 				}
   2405 
   2406 				EFUN(falcon_tsc_uc_lane_idx_to_system_id(uc_lane_id_str, cc));
   2407 				EFUN_PRINTF(("  Lane %s: ", uc_lane_id_str));
   2408 #ifdef SERDES_API_FLOATING_POINT
   2409 				EFUN_PRINTF(("  t= %.2f ms", curr_time));
   2410 #else
   2411 				EFUN_PRINTF(("  t= %d ms", curr_time));
   2412 #endif
   2413 				prev_time = curr_time;
   2414 				prev_rr = rr;
   2415 
   2416 				prev_event = *(trace_mem + (++addr));
   2417 				switch (prev_event) {
   2418 				case EVENT_CODE_CL72_READY_FOR_COMMAND:
   2419 				case EVENT_CODE_EACH_WRITE_TO_CL72_TX_CHANGE_REQUEST:
   2420 				case EVENT_CODE_CL72_LOCAL_TX_CHANGED:
   2421 					if (rr != NOR_ENTRY_SIZE) {
   2422 						post_cursor = (*(trace_mem + (++addr)) & 0x30) >> 4;
   2423 						curr_cursor = (*(trace_mem + addr) & 0x0C) >> 2;
   2424 						prev_cursor = *(trace_mem + addr) & 0x03;
   2425 						addr--;                                 /* rewind to populate supplement info */
   2426 					}
   2427 					break;
   2428 				case EVENT_CODE_GENERAL_EVENT_0:
   2429 				case EVENT_CODE_GENERAL_EVENT_1:
   2430 				case EVENT_CODE_GENERAL_EVENT_2:
   2431 					post_cursor = *(trace_mem + (++addr));
   2432 					prev_cursor = *(trace_mem + (++addr));
   2433 					addr -= 2;                                     /* rewind to populate supplement info */
   2434 					break;
   2435 				case EVENT_CODE_ERROR_EVENT:
   2436 					post_cursor = *(trace_mem + (++addr));
   2437 					addr--;
   2438 					break;
   2439 				case EVENT_CODE_SM_STATUS_RESTART:
   2440 					post_cursor = *(trace_mem + (++addr));
   2441 					addr--;
   2442 					break;
   2443 				default:
   2444 					break;
   2445 				}
   2446 
   2447 				/* retrieve supplement info, if any */
   2448 				for (cc = 0; cc < rr - NOR_ENTRY_SIZE; cc++)
   2449 					supp_info[cc] = *(trace_mem + (++addr));
   2450 
   2451 				addr++;
   2452 			}
   2453 		}
   2454 	}
   2455 
   2456 	return ERR_CODE_NONE;
   2457 }
   2458 
   2459 
   2460 err_code_t falcon_tsc_display_state (const phymod_access_t *pa){
   2461 	EFUN(falcon_tsc_display_core_state (pa ));
   2462 	EFUN(falcon_tsc_display_lane_state_hdr (pa ));
   2463 	EFUN(falcon_tsc_display_lane_state (pa ));
   2464 	EFUN(falcon_tsc_display_lane_state_legend (pa ));
   2465 	return ERR_CODE_NONE;
   2466 }
   2467 
   2468 err_code_t falcon_tsc_display_config (const phymod_access_t *pa){
   2469 	EFUN(falcon_tsc_display_core_config (pa ));
   2470 	EFUN(falcon_tsc_display_lane_config (pa ));
   2471 	return ERR_CODE_NONE;
   2472 }
   2473 
   2474 
   2475 /**********************************************/
   2476 /*  Temperature forcing and reading           */
   2477 /**********************************************/
   2478 
   2479 err_code_t falcon_tsc_force_die_temperature (const phymod_access_t *pa, int16_t die_temp){
   2480 	/* Formula for PVTMON: T = 410.04-0.48705*reg10bit (from PVTMON Analog Module Specification v5.0 section 6.2) */
   2481 	int32_t die_temp_int;
   2482 
   2483 	if (die_temp > 130)
   2484 		die_temp = 130;
   2485 	if (die_temp < -45)
   2486 		die_temp = -45;
   2487 
   2488 	die_temp_int = (int32_t)die_temp;
   2489 	EFUN(wrcv_temp_frc_val((uint16_t)((431045 - ((die_temp_int << 10) + (die_temp_int << 4) + (die_temp_int << 3) + (die_temp_int << 1) + die_temp_int)) >> 9)));
   2490 
   2491 	return ERR_CODE_NONE;
   2492 }
   2493 
   2494 err_code_t falcon_tsc_read_die_temperature (const phymod_access_t *pa, int16_t *die_temp){
   2495 
   2496 	uint16_t die_temp_sensor_reading;
   2497 
   2498 	EFUN(falcon_tsc_pmd_uc_cmd (pa, CMD_UC_DBG, CMD_UC_DBG_DIE_TEMP, 100));
   2499 	ESTM(die_temp_sensor_reading = rd_uc_dsc_data());
   2500 	*die_temp = _bin_to_degC(die_temp_sensor_reading);
   2501 
   2502 	return ERR_CODE_NONE;
   2503 }
   2504 
   2505 
   2506 err_code_t falcon_tsc_read_die_temperature_double (const phymod_access_t *pa, USR_DOUBLE *die_temp){
   2507 #ifdef SERDES_API_FLOATING_POINT
   2508 	/* Formula for PVTMON: T = 410.04-0.48705*reg10bit (from PVTMON Analog Module Specification v5.0 section 6.2) */
   2509 	uint16_t die_temp_sensor_reading;
   2510 
   2511 	EFUN(falcon_tsc_pmd_uc_cmd (pa, CMD_UC_DBG, CMD_UC_DBG_DIE_TEMP, 100));
   2512 	ESTM(die_temp_sensor_reading = rd_uc_dsc_data());
   2513 
   2514 	*die_temp = 410.04 - 0.48705 * ((USR_DOUBLE)die_temp_sensor_reading);
   2515 
   2516 	return ERR_CODE_NONE;
   2517 #else
   2518 	EFUN_PRINTF((" Function 'falcon_tsc_read_die_temperature_double' needs SERDES_API_FLOATING_POINT defined to operate \n"));
   2519 	return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   2520 #endif
   2521 }
   2522 
   2523 
   2524 
   2525