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