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

eagle_tsc_functions.c (106705B)


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