openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

merlin16_pcieg3_internal.c (52012B)


      1 /***********************************************************************************
      2  ***********************************************************************************
      3  *  File Name     :  merlin16_pcieg3_internal.c                                         *
      4  *  Created On    :  13/02/2014                                                    *
      5  *  Created By    :  Justin Gaither                                                *
      6  *  Description   :  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_internal.c
     23  * Implementation of API functions
     24  */
     25 
     26 #include "merlin16_pcieg3_internal.h"
     27 #include "merlin16_pcieg3_internal_error.h"
     28 #include "merlin16_pcieg3_access.h"
     29 #include "merlin16_pcieg3_common.h"
     30 #include "merlin16_pcieg3_config.h"
     31 #include "merlin16_pcieg3_functions.h"
     32 #include "merlin16_pcieg3_select_defns.h"
     33 #include "merlin16_pcieg3_prbs.h"
     34 
     35 #ifndef UINT16_MAX 
     36 #define UINT16_MAX (65535U)
     37 #endif
     38 
     39 /* If SERDES_EVAL is defined, then is_ate_log_enabled() is queried to *\
     40 \* know whether to log ATE.  merlin16_pcieg3_access.h provides that function.  */
     41 
     42 
     43 static merlin16_pcieg3_info_t merlin16_pcieg3_info;
     44 
     45 merlin16_pcieg3_info_t *merlin16_pcieg3_INTERNAL_get_merlin16_pcieg3_info_ptr(void) {
     46     return &merlin16_pcieg3_info;
     47 }
     48 
     49 err_code_t merlin16_pcieg3_INTERNAL_verify_merlin16_pcieg3_info(merlin16_pcieg3_info_t const *test_info)
     50 {
     51     if (test_info->signature != SRDS_INFO_SIGNATURE) {
     52         EFUN_PRINTF(("ERROR:  Mismatch in merlin16_pcieg3_info signature.  Expected 0x%08X, but received 0x%08X.\n",
     53                      SRDS_INFO_SIGNATURE, test_info->signature));
     54         return (_error(ERR_CODE_INFO_TABLE_ERROR));
     55     }
     56     return (ERR_CODE_NONE);
     57 }
     58 
     59 /* Store a cached AFE version for re-use */
     60 err_code_t merlin16_pcieg3_INTERNAL_get_afe_hw_version(srds_access_t *sa__, uint8_t *afe_hw_version) {
     61   static uint8_t _cached_afe_hw_version = 255;
     62   
     63   if (!afe_hw_version)
     64     return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
     65   if (_cached_afe_hw_version == 255)
     66     ESTM(_cached_afe_hw_version = rdcv_afe_hardware_version());
     67   *afe_hw_version = _cached_afe_hw_version;
     68   return(ERR_CODE_NONE);
     69 }
     70 
     71 int merlin16_pcieg3_osr_mode_enum_to_int_x1000(uint8_t osr_mode) {
     72     switch(osr_mode) {
     73     case MERLIN16_PCIEG3_OSX1:      return 1000;
     74     case MERLIN16_PCIEG3_OSX2:      return 2000;
     75     case MERLIN16_PCIEG3_OSX4:      return 4000;
     76     case MERLIN16_PCIEG3_OSX3:      return 3000;
     77     case MERLIN16_PCIEG3_OSX3P3:    return 3300;
     78     case MERLIN16_PCIEG3_OSX5:      return 5000;
     79     case MERLIN16_PCIEG3_OSX7P5:    return 7500;
     80     case MERLIN16_PCIEG3_OSX8P25:   return 8250;
     81     case MERLIN16_PCIEG3_OSX10:     return 10000;
     82     case MERLIN16_PCIEG3_OSX8:      return 8000;
     83     default:                    return 1000;
     84     }
     85 }
     86 
     87 err_code_t merlin16_pcieg3_INTERNAL_get_num_bits_per_ms(srds_access_t *sa__, uint32_t *num_bits_per_ms) {
     88     uint8_t osr_mode = 0;
     89 #if defined(rd_rx_pam4_mode)
     90     uint8_t pam4_mode = 0;
     91 #endif
     92     struct merlin16_pcieg3_uc_core_config_st core_config = {{0}};
     93 
     94     ESTM(osr_mode = rd_rx_osr_mode());
     95 
     96 #if defined(rd_rx_pam4_mode)
     97     ESTM(pam4_mode = rd_rx_pam4_mode());
     98 #endif
     99 
    100         *num_bits_per_ms = (((uint32_t)core_config.vco_rate_in_Mhz * 100000UL) / merlin16_pcieg3_osr_mode_enum_to_int_x1000(osr_mode))*10;
    101 
    102 #if defined(rd_rx_pam4_mode)
    103     if(pam4_mode > 0) *num_bits_per_ms <<= 1; 
    104 #endif
    105     return(ERR_CODE_NONE);
    106 }
    107 
    108 err_code_t merlin16_pcieg3_INTERNAL_display_BER(srds_access_t *sa__, uint16_t time_ms) {
    109     char string[10];
    110     EFUN(merlin16_pcieg3_INTERNAL_get_BER_string(sa__,time_ms,string));
    111     USR_PRINTF(("%s",string));
    112     return(ERR_CODE_NONE);
    113 }
    114 
    115 err_code_t merlin16_pcieg3_INTERNAL_get_BER_string(srds_access_t *sa__, uint16_t time_ms, char *string) {
    116     char string2[3];
    117     struct ber_data_st ber_data = {0, 0, 0, 0};
    118 
    119     if(string == NULL) {
    120         return(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
    121     }
    122 
    123     EFUN(merlin16_pcieg3_INTERNAL_get_BER_data(sa__, time_ms, &ber_data));
    124 
    125     if(ber_data.prbs_chk_en == 0) {
    126         USR_STRCPY(string,"");
    127         return(ERR_CODE_NONE);
    128     } else {
    129         USR_STRCPY(string2," ");
    130     }
    131 
    132     if((ber_data.num_errs < 3) && (ber_data.lcklost == 0)) {   /* lcklost = 0 */
    133         USR_STRNCAT(string2,"<",1);
    134         ber_data.num_errs = 3;
    135     } else {
    136         USR_STRNCAT(string2," ",1);
    137     }
    138     if(ber_data.lcklost == 1) {    /* lcklost = 1 */
    139         USR_STRCPY(string,"  !Lock ");
    140     } else {                    /* lcklost = 0 */
    141         uint16_t x=0,y=0,z=0,div;
    142 
    143         if(ber_data.num_errs >= ber_data.num_bits) {
    144             x = 1;y=0;z=0;
    145         }else {
    146             while(1) {
    147                 div = (uint16_t)(((ber_data.num_errs<<1) + ber_data.num_bits)/(ber_data.num_bits<<1));
    148                 if(div>=10) break;
    149                 ber_data.num_errs = ber_data.num_errs*10;
    150                 z=z+1;
    151             }
    152             if(div>=100) {
    153                 div = div/10;
    154                 z=z-1;
    155             }
    156             x=div/10;
    157             y = div - 10*x;
    158             z=z-1;
    159             USR_SPRINTF((string,"%s%d.%1de-%02d",string2,x,y,z));
    160         }
    161 
    162     }
    163     return(ERR_CODE_NONE);
    164 
    165 }
    166 
    167 err_code_t merlin16_pcieg3_INTERNAL_get_BER_data(srds_access_t *sa__, uint16_t time_ms, struct ber_data_st *ber_data) {
    168     uint8_t lcklost = 0;
    169     uint32_t err_cnt= 0;
    170 
    171     if(ber_data == NULL) {
    172         return(ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
    173     }
    174 
    175     ESTM(ber_data->prbs_chk_en = rd_prbs_chk_en());
    176     if(ber_data->prbs_chk_en == 0)
    177         return(ERR_CODE_NONE);
    178 
    179     EFUN(merlin16_pcieg3_prbs_err_count_state(sa__, &err_cnt,&lcklost)); /* clear error counters */
    180     EFUN(USR_DELAY_MS(time_ms));
    181     EFUN(merlin16_pcieg3_prbs_err_count_state(sa__, &err_cnt,&lcklost)); 
    182 
    183     ber_data->lcklost = lcklost;
    184 
    185     if(ber_data->lcklost == 0) {
    186         uint32_t num_bits_per_ms=0;
    187 
    188         EFUN(merlin16_pcieg3_INTERNAL_get_num_bits_per_ms(sa__,&num_bits_per_ms));
    189 
    190         ber_data->num_errs = err_cnt;
    191         ber_data->num_bits = (uint64_t)num_bits_per_ms*(uint64_t)time_ms;
    192     }
    193     return(ERR_CODE_NONE);
    194 
    195 }
    196 
    197 
    198 err_code_t merlin16_pcieg3_INTERNAL_get_p1_threshold(srds_access_t *sa__, int8_t *val) {
    199  ESTM(*val = -rd_p1_eyediag_bin()); 
    200  return (ERR_CODE_NONE);
    201 }
    202 
    203 
    204 int16_t merlin16_pcieg3_INTERNAL_ladder_setting_to_mV(srds_access_t *sa__, int8_t ctrl, uint8_t range_250) {
    205     uint16_t absv;                                    /* Absolute value of ctrl */
    206     int16_t nlmv;                                     /* Non-linear value */
    207     
    208     /* Get absolute value */
    209     absv = SRDS_ABS(ctrl);
    210 
    211     { 
    212         if (range_250) {
    213             /* 28nm range is 250mV, but 16nm range is 200mV */
    214             /* 200mV range, 6.5519mV linear units */
    215             nlmv = absv*190/29;
    216         }
    217         else {
    218             /* 120mV range, 3.8854mV linear units */
    219             nlmv = absv*136/35;
    220         }
    221     }
    222     /* Add sign and return */
    223     return( (ctrl>=0) ? nlmv : -nlmv);
    224 }
    225 
    226 
    227 err_code_t merlin16_pcieg3_INTERNAL_compute_bin(char var, char bin[]) {
    228     if(!bin) {
    229         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    230     }
    231 
    232   switch (var) {
    233     case '0':  ENULL_STRCPY(bin,"0000");
    234                break;
    235     case '1':  ENULL_STRCPY(bin,"0001");
    236                break;
    237     case '2':  ENULL_STRCPY(bin,"0010");
    238                break;
    239     case '3':  ENULL_STRCPY(bin,"0011");
    240                break;
    241     case '4':  ENULL_STRCPY(bin,"0100");
    242                break;
    243     case '5':  ENULL_STRCPY(bin,"0101");
    244                break;
    245     case '6':  ENULL_STRCPY(bin,"0110");
    246                break;
    247     case '7':  ENULL_STRCPY(bin,"0111");
    248                break;
    249     case '8':  ENULL_STRCPY(bin,"1000");
    250                break;
    251     case '9':  ENULL_STRCPY(bin,"1001");
    252                break;
    253     case 'a':
    254     case 'A':  ENULL_STRCPY(bin,"1010");
    255                break;
    256     case 'b':
    257     case 'B':  ENULL_STRCPY(bin,"1011");
    258                break;
    259     case 'c':
    260     case 'C':  ENULL_STRCPY(bin,"1100");
    261                break;
    262     case 'd':
    263     case 'D':  ENULL_STRCPY(bin,"1101");
    264                break;
    265     case 'e':
    266     case 'E':  ENULL_STRCPY(bin,"1110");
    267                break;
    268     case 'f':
    269     case 'F':  ENULL_STRCPY(bin,"1111");
    270                break;
    271     case '_':  ENULL_STRCPY(bin,"");
    272                break;
    273     default :  ENULL_STRCPY(bin,"");
    274                EFUN_PRINTF(("ERROR: Invalid Hexadecimal Pattern\n"));
    275                return (_error(ERR_CODE_CFG_PATT_INVALID_HEX));
    276   }
    277   return (ERR_CODE_NONE);
    278 }
    279 
    280 
    281 err_code_t merlin16_pcieg3_INTERNAL_compute_hex(char bin[],uint8_t *hex) {
    282   if(!hex) {
    283     return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    284   }
    285  
    286   if (!USR_STRCMP(bin,"0000")) {
    287     *hex = 0x0;
    288   } 
    289   else if (!USR_STRCMP(bin,"0001")) {
    290     *hex = 0x1;
    291   } 
    292   else if (!USR_STRCMP(bin,"0010")) {
    293     *hex = 0x2;
    294   } 
    295   else if (!USR_STRCMP(bin,"0011")) {
    296     *hex = 0x3;
    297   } 
    298   else if (!USR_STRCMP(bin,"0100")) {
    299     *hex = 0x4;
    300   } 
    301   else if (!USR_STRCMP(bin,"0101")) {
    302     *hex = 0x5;
    303   } 
    304   else if (!USR_STRCMP(bin,"0110")) {
    305     *hex = 0x6;
    306   } 
    307   else if (!USR_STRCMP(bin,"0111")) {
    308     *hex = 0x7;
    309   } 
    310   else if (!USR_STRCMP(bin,"1000")) {
    311     *hex = 0x8;
    312   } 
    313   else if (!USR_STRCMP(bin,"1001")) {
    314     *hex = 0x9;
    315   } 
    316   else if (!USR_STRCMP(bin,"1010")) {
    317     *hex = 0xA;
    318   } 
    319   else if (!USR_STRCMP(bin,"1011")) {
    320     *hex = 0xB;
    321   } 
    322   else if (!USR_STRCMP(bin,"1100")) {
    323     *hex = 0xC;
    324   } 
    325   else if (!USR_STRCMP(bin,"1101")) {
    326     *hex = 0xD;
    327   } 
    328   else if (!USR_STRCMP(bin,"1110")) {
    329     *hex = 0xE;
    330   } 
    331   else if (!USR_STRCMP(bin,"1111")) {
    332     *hex = 0xF;
    333   } 
    334   else {
    335     EFUN_PRINTF(("ERROR: Invalid Binary to Hex Conversion\n"));
    336     *hex = 0x0;
    337     return (_error(ERR_CODE_CFG_PATT_INVALID_BIN2HEX));
    338   } 
    339   return (ERR_CODE_NONE);
    340 }
    341 
    342 uint8_t merlin16_pcieg3_INTERNAL_stop_micro(srds_access_t *sa__, uint8_t graceful, err_code_t *err_code_p) {
    343    uint8_t stop_state = 0;
    344 
    345    if(!err_code_p) {
    346        return(0xFF);
    347    }
    348 
    349    /* Log current micro stop status */
    350    EPSTM2((stop_state = rdv_usr_sts_micro_stopped()),0xFF);
    351 
    352    if(graceful) {
    353        if (!(stop_state & 0x7F)) {
    354            EPFUN2((merlin16_pcieg3_stop_rx_adaptation(sa__, 1)),0xFF);
    355        }
    356    } else {
    357        EPFUN2((merlin16_pcieg3_pmd_uc_control(sa__, CMD_UC_CTRL_STOP_IMMEDIATE,GRACEFUL_STOP_TIME)),0xFF);
    358    }
    359 
    360    /* Return the previous micro stop status */
    361    return(stop_state);
    362 }
    363 
    364 
    365   
    366 
    367 /********************************************************/
    368 /*  Global RAM access through Micro Register Interface  */
    369 /********************************************************/
    370 /* Micro Global RAM Byte Read */
    371 uint8_t merlin16_pcieg3_INTERNAL_rdb_uc_var(srds_access_t *sa__, err_code_t *err_code_p, uint16_t addr) {
    372     uint8_t rddata;
    373 
    374     if(!err_code_p) {
    375         return(0);
    376     }
    377     EPSTM(rddata = merlin16_pcieg3_rdb_uc_ram(sa__, err_code_p, addr)); /* Use Micro register interface for reading RAM */
    378     return (rddata);
    379 }
    380 
    381 /* Micro Global RAM Word Read */
    382 uint16_t merlin16_pcieg3_INTERNAL_rdw_uc_var(srds_access_t *sa__, err_code_t *err_code_p, uint16_t addr) {
    383   uint16_t rddata;
    384 
    385   if(!err_code_p) {
    386       return(0);
    387   }
    388   if (addr%2 != 0) {                                         /* Validate even address */
    389       *err_code_p = ERR_CODE_INVALID_RAM_ADDR;
    390       USR_PRINTF(("Error incorrect addr x%04x\n",addr));
    391       return (0);
    392   }
    393   EPSTM(rddata = merlin16_pcieg3_rdw_uc_ram(sa__, err_code_p, (addr))); /* Use Micro register interface for reading RAM */
    394   return (rddata);
    395 }
    396 
    397 /* Micro Global RAM Byte Write  */
    398 err_code_t merlin16_pcieg3_INTERNAL_wrb_uc_var(srds_access_t *sa__, uint16_t addr, uint8_t wr_val) {
    399 
    400     return (merlin16_pcieg3_wrb_uc_ram(sa__, addr, wr_val));          /* Use Micro register interface for writing RAM */
    401 }
    402 
    403 /* Micro Global RAM Word Write  */
    404 err_code_t merlin16_pcieg3_INTERNAL_wrw_uc_var(srds_access_t *sa__, uint16_t addr, uint16_t wr_val) {
    405     if (addr%2 != 0) {                                       /* Validate even address */
    406       USR_PRINTF(("Error incorrect addr x%04x\n",addr));
    407         return (_error(ERR_CODE_INVALID_RAM_ADDR));
    408     }
    409     return (merlin16_pcieg3_wrw_uc_ram(sa__, addr, wr_val));          /* Use Micro register interface for writing RAM */
    410 }
    411 
    412 
    413 /***********************/
    414 /*  Event Log Display  */
    415 /***********************/
    416 err_code_t merlin16_pcieg3_INTERNAL_event_log_dump_callback(void *arg, uint8_t byte_count, uint16_t data) {
    417     merlin16_pcieg3_INTERNAL_event_log_dump_state_t * const state_ptr = (merlin16_pcieg3_INTERNAL_event_log_dump_state_t *)arg;
    418     const uint8_t bytes_per_row=16;
    419 
    420     if (byte_count == 0) {
    421         if (state_ptr->line_start_index != state_ptr->index) {
    422             EFUN_PRINTF(("%*s    %d\n", 4*(bytes_per_row - state_ptr->index + state_ptr->line_start_index), "", state_ptr->line_start_index));
    423         }
    424         return (ERR_CODE_NONE);
    425     }
    426     if (byte_count == 1) {
    427         /* There is a trailing byte in the event log.
    428          * The simplest way to handle it is to print out a whole word, but mask
    429          * the invalid upper byte.
    430          */
    431         data &= 0xFF;
    432     }
    433     EFUN_PRINTF(("  0x%04x", ((data & 0xFF) << 8) | (data >> 8)));
    434     state_ptr->index += 2;
    435     if (state_ptr->index % bytes_per_row == 0) {
    436         EFUN_PRINTF(("    %d\n", state_ptr->line_start_index));
    437         state_ptr->line_start_index = state_ptr->index;
    438     }
    439 
    440     return(ERR_CODE_NONE);
    441 }
    442 
    443 err_code_t merlin16_pcieg3_INTERNAL_read_event_log_with_callback(srds_access_t *sa__,
    444                                                         uint8_t micro_num,
    445                                                         uint8_t bypass_micro,
    446                                                         void *arg,
    447                                                         err_code_t (*callback)(void *, uint8_t, uint16_t)) {
    448     merlin16_pcieg3_info_t const * const merlin16_pcieg3_info_ptr = merlin16_pcieg3_INTERNAL_get_merlin16_pcieg3_info_ptr();
    449     uint16_t rd_idx;
    450     uint8_t current_lane;
    451 
    452     EFUN(merlin16_pcieg3_INTERNAL_verify_merlin16_pcieg3_info(merlin16_pcieg3_info_ptr));
    453 
    454     if (micro_num >= merlin16_pcieg3_info_ptr->micro_count) {
    455         return (_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    456     }
    457     /* Read Current lane so that it can be restored at the end of function */
    458     current_lane = merlin16_pcieg3_get_lane(sa__);
    459     EFUN_PRINTF(("\n\n********************************************\n"));
    460     EFUN_PRINTF((    "**** SERDES UC TRACE MEMORY DUMP ***********\n"));
    461     EFUN_PRINTF((    "********************************************\n"));
    462 
    463     if (bypass_micro) {
    464         ESTM(rd_idx = rdcv_trace_mem_wr_idx());
    465         if (merlin16_pcieg3_info_ptr->trace_memory_descending_writes) {
    466             ++rd_idx;
    467             if (rd_idx >= merlin16_pcieg3_info_ptr->trace_mem_ram_size) {
    468                 rd_idx = 0;
    469             }
    470         } else {
    471             if (rd_idx == 0) {
    472                 rd_idx = merlin16_pcieg3_info_ptr->trace_mem_ram_size;
    473             }
    474             --rd_idx;
    475         }
    476     } else {
    477         /* Start Read to stop uC logging and read the word at last event written by uC */
    478         EFUN(merlin16_pcieg3_pmd_uc_cmd(sa__, CMD_EVENT_LOG_READ, CMD_EVENT_LOG_READ_START, GRACEFUL_STOP_TIME));
    479         ESTM(rd_idx = rdcv_trace_mem_rd_idx());
    480     }
    481     
    482     EFUN_PRINTF(( "\n  DEBUG INFO: trace memory read index = 0x%04x\n", rd_idx));
    483     
    484     EFUN_PRINTF(("  DEBUG INFO: trace memory size = 0x%04x\n\n", merlin16_pcieg3_info_ptr->trace_mem_ram_size));
    485 
    486     if (merlin16_pcieg3_info_ptr->trace_memory_descending_writes) {
    487         /* Micro writes trace memory using descending addresses.
    488          * So read using ascending addresses using block read
    489          */
    490         EFUN(merlin16_pcieg3_INTERNAL_rdblk_uc_generic_ram(sa__,
    491                                                   merlin16_pcieg3_info_ptr->trace_mem_ram_base + merlin16_pcieg3_info_ptr->grp_ram_size*micro_num,
    492                                                   merlin16_pcieg3_info_ptr->trace_mem_ram_size,
    493                                                   rd_idx,
    494                                                   merlin16_pcieg3_info_ptr->trace_mem_ram_size,
    495                                                   arg,
    496                                                   callback));
    497     } else {
    498         /* Micro writes trace memory using descending addresses.
    499          * So read using ascending addresses using block read
    500          */
    501         EFUN(merlin16_pcieg3_INTERNAL_rdblk_uc_generic_ram_descending(sa__,
    502                                                              merlin16_pcieg3_info_ptr->trace_mem_ram_base + merlin16_pcieg3_info_ptr->grp_ram_size*micro_num,
    503                                                              merlin16_pcieg3_info_ptr->trace_mem_ram_size,
    504                                                              rd_idx,
    505                                                              merlin16_pcieg3_info_ptr->trace_mem_ram_size,
    506                                                              arg,
    507                                                              callback));
    508     }
    509 
    510     if (!bypass_micro) {
    511         /* Read Done to resume logging  */
    512         EFUN(merlin16_pcieg3_pmd_uc_cmd(sa__, CMD_EVENT_LOG_READ, CMD_EVENT_LOG_READ_DONE, 50));
    513     }
    514     EFUN(merlin16_pcieg3_set_lane(sa__,current_lane));
    515     return(ERR_CODE_NONE);
    516 }
    517 
    518 #ifdef TO_FLOATS
    519 /* convert uint32_t to float8 */
    520 float8_t merlin16_pcieg3_INTERNAL_int32_to_float8(uint32_t input) {
    521     int8_t cnt;
    522     uint8_t output;
    523     
    524     if(input == 0) {
    525       return(0);
    526     } else if(input == 1) {
    527       return(0xe0);
    528     } else {
    529       cnt = 0;
    530       input = input & 0x7FFFFFFF; /* get rid of MSB which may be lock indicator */
    531       do {
    532         input = input << 1;
    533         cnt++;
    534       } while ((input & 0x80000000) == 0);
    535     
    536       output = (uint8_t)((input & 0x70000000)>>23)+(31 - cnt%32);
    537       return(output);
    538     }
    539 }
    540 #endif
    541 
    542 /* convert float8 to uint32_t */
    543 uint32_t merlin16_pcieg3_INTERNAL_float8_to_int32(float8_t input) {
    544     uint32_t x;
    545     if(input == 0) return(0);
    546     x = (input>>5) + 8;
    547     if((input & 0x1F) < 3) {
    548       return(x>>(3-(input & 0x1f)));
    549     } 
    550     return(x<<((input & 0x1F)-3));
    551 }
    552 
    553 /* Convert uint8 to 8-bit gray code */
    554 uint8_t merlin16_pcieg3_INTERNAL_uint8_to_gray(uint8_t input) {
    555     return input ^ (input >> 1);
    556 }
    557 
    558 /* Convert 8-bit gray code to uint8 */
    559 uint8_t merlin16_pcieg3_INTERNAL_gray_to_uint8(uint8_t input) {
    560     input = input ^ (input >> 4);
    561     input = input ^ (input >> 2);
    562     input = input ^ (input >> 1);
    563     return input;
    564 }
    565 
    566 
    567 /* convert float12 to uint32 */
    568 uint32_t merlin16_pcieg3_INTERNAL_float12_to_uint32(uint8_t byte, uint8_t multi) {
    569 
    570     return(((uint32_t)byte)<<multi);
    571 }
    572 
    573 #ifdef TO_FLOATS
    574 /* convert uint32 to float12 */
    575 uint8_t merlin16_pcieg3_INTERNAL_uint32_to_float12(uint32_t input, uint8_t *multi) {
    576     int8_t cnt;
    577     uint8_t output;
    578     if(!multi) {
    579       return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    580     }
    581     
    582     if((input == 0) || (!multi)) {
    583       *multi = 0;
    584       return(0);
    585     } else {
    586       cnt = 0;
    587       if(input > 0x007FFFFF) input = 0x007FFFFF; /* limit to 23bits so multi is 4 bits */
    588       do {
    589         input = input << 1;
    590         cnt++;
    591       } while ((input & 0x80000000) == 0);
    592       
    593       *multi = (31 - (cnt%32));
    594       if(*multi < 8) {
    595         output = (uint8_t)((input & 0xFF000000)>>(24 + (7-*multi)));
    596         *multi = 0;
    597       } else {
    598         output = (uint8_t)((input & 0xFF000000)>>24);
    599         *multi = *multi - 7;
    600       }
    601       return(output);
    602     }
    603 }
    604 #endif
    605 
    606 err_code_t merlin16_pcieg3_INTERNAL_set_rx_pf_main(srds_access_t *sa__, uint8_t val) {
    607     if (val > 15) {
    608       return (_error(ERR_CODE_PF_INVALID));
    609     }
    610     EFUN(WR_RX_PF_CTRL(val));
    611     return(ERR_CODE_NONE); 
    612 }
    613 
    614 err_code_t merlin16_pcieg3_INTERNAL_get_rx_pf_main(srds_access_t *sa__, int8_t *val) {
    615     ESTM(*val = (int8_t)RD_RX_PF_CTRL());
    616     return (ERR_CODE_NONE);
    617 }
    618 
    619 err_code_t merlin16_pcieg3_INTERNAL_set_rx_pf2(srds_access_t *sa__, uint8_t val) {
    620     if (val > 7) {
    621       return (_error(ERR_CODE_PF_INVALID));
    622     }
    623     EFUN(WR_RX_PF2_CTRL(val));
    624     return(ERR_CODE_NONE); 
    625 }
    626 
    627 err_code_t merlin16_pcieg3_INTERNAL_get_rx_pf2(srds_access_t *sa__, int8_t *val) {
    628     ESTM(*val = (int8_t)RD_RX_PF2_CTRL());
    629     return (ERR_CODE_NONE);
    630 }
    631 
    632 
    633 err_code_t merlin16_pcieg3_INTERNAL_set_rx_vga(srds_access_t *sa__, uint8_t val) {
    634 
    635     EFUN(merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(sa__));  /* make sure uC is stopped to avoid race conditions */
    636 
    637     if (val > RX_VGA_CTRL_VAL_MAX) {
    638       return (_error(ERR_CODE_VGA_INVALID));
    639     }
    640 #if defined(RX_VGA_CTRL_VAL_MIN) && (RX_VGA_CTRL_VAL_MIN > 0)
    641     if (val < RX_VGA_CTRL_VAL_MIN) {
    642       return (_error(ERR_CODE_VGA_INVALID));
    643     } 
    644 #endif
    645     
    646     {
    647         uint8_t rate_sel;
    648         ESTM(rate_sel = rd_rate_sel());
    649         if (rate_sel < MERLIN16_PCIEG3_GEN3) {
    650             if (val <= 15) {
    651                 EFUN(wr_rx_vga1_ctrl_G1G2(val));
    652                 EFUN(wr_rx_vga2_ctrl_G1G2(0));
    653                 EFUN(wr_rx_vga3_ctrl_G1G2(0));
    654             } else if (val <= 30) {
    655                 EFUN(wr_rx_vga1_ctrl_G1G2(15));
    656                 EFUN(wr_rx_vga2_ctrl_G1G2(val-15));
    657                 EFUN(wr_rx_vga3_ctrl_G1G2(0));
    658             }else{
    659                 EFUN(wr_rx_vga1_ctrl_G1G2(15));
    660                 EFUN(wr_rx_vga2_ctrl_G1G2(15));
    661                 EFUN(wr_rx_vga3_ctrl_G1G2(val-30));
    662             }
    663         } else {
    664             EFUN(wr_hwtune_ovr_write_sel(0));                   /* Configure hwtune_ovr_write_sel to VGA */
    665             EFUN(wr_hwtune_ovr_write_val(val<<3));              /* hwtune_ovr_write_val[8:3] are used to drive the analog control port */
    666             EFUN(wr_hwtune_ovr_write_en(1));
    667         }
    668     }
    669     return(ERR_CODE_NONE); 
    670 }
    671 
    672 err_code_t merlin16_pcieg3_INTERNAL_get_rx_vga(srds_access_t *sa__, int8_t *val) {
    673     {
    674         uint8_t rate_sel;
    675         ESTM(rate_sel = rd_rate_sel());
    676         if (rate_sel < MERLIN16_PCIEG3_GEN3) {
    677             ESTM(*val = (int8_t)(rd_rx_vga1_ctrl_G1G2() + rd_rx_vga2_ctrl_G1G2() + rd_rx_vga3_ctrl_G1G2()));
    678         } else {
    679     ESTM(*val = (int8_t)rd_vga_bin());
    680         }
    681     }
    682     return (ERR_CODE_NONE);
    683 }
    684 
    685 
    686 err_code_t merlin16_pcieg3_INTERNAL_set_rx_dfe1(srds_access_t *sa__, int8_t val) {
    687 
    688     EFUN(merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(sa__));  /* make sure uC is stopped to avoid race conditions */
    689 
    690     {
    691         int8_t tap_eo;
    692 
    693         if (val > 63) {
    694             return (_error(ERR_CODE_DFE1_INVALID));  
    695         }
    696         /* Compute tap1 even/odd component */
    697         tap_eo = 0;                                      /* Not supporting dfe_dcd values */
    698         EFUN(wr_hwtune_ovr_write_sel(2));                /* Write tap1_odd */
    699         EFUN(wr_hwtune_ovr_write_val(tap_eo));
    700         EFUN(wr_hwtune_ovr_write_en(1));
    701         EFUN(wr_hwtune_ovr_write_sel(3));                /* Write tap1_even */
    702         EFUN(wr_hwtune_ovr_write_val(tap_eo));
    703         EFUN(wr_hwtune_ovr_write_en(1));
    704         EFUN(wr_hwtune_ovr_write_sel(1));
    705         EFUN(wr_hwtune_ovr_write_val(val-tap_eo));       /* Write the common tap */
    706         EFUN(wr_hwtune_ovr_write_en(1));
    707     }
    708     return(ERR_CODE_NONE); 
    709 }
    710 err_code_t merlin16_pcieg3_INTERNAL_get_rx_dfe1(srds_access_t *sa__, int8_t *val) {
    711     ESTM(*val = (int8_t)(rd_dfe_1_e() + rd_dfe_1_cmn()));
    712     return (ERR_CODE_NONE);
    713 }
    714 
    715 
    716 err_code_t merlin16_pcieg3_INTERNAL_set_rx_dfe2(srds_access_t *sa__, int8_t val) {
    717     int8_t tap_eo;
    718 
    719     if ((val > 31) || (val < -31)) {
    720       return (_error(ERR_CODE_DFE2_INVALID));  
    721     }
    722 
    723     EFUN(merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(sa__));  /* make sure uC is stopped to avoid race conditions */
    724 
    725     /* Compute tap2 odd/even component */
    726     tap_eo = 0;                                         /* Not supporting dfe_dcd values */
    727     EFUN(wr_hwtune_ovr_write_sel(5));                   /* Write tap2_odd */
    728     EFUN(wr_hwtune_ovr_write_val(tap_eo));
    729     EFUN(wr_hwtune_ovr_write_en(1));
    730     EFUN(wr_hwtune_ovr_write_sel(6));                   /* Write tap2_even */
    731     EFUN(wr_hwtune_ovr_write_val(tap_eo));
    732     EFUN(wr_hwtune_ovr_write_en(1));
    733     EFUN(wr_hwtune_ovr_write_sel(4));
    734     EFUN(wr_hwtune_ovr_write_val(SRDS_ABS(val)-tap_eo));/* Write the common tap */
    735     EFUN(wr_hwtune_ovr_write_en(1));
    736     EFUN(wr_hwtune_ovr_write_sel(10));                  /* Write tap2_even_sign */
    737     EFUN(wr_hwtune_ovr_write_val(val<0?1:0));
    738     EFUN(wr_hwtune_ovr_write_en(1));
    739     EFUN(wr_hwtune_ovr_write_sel(11));                  /* Write tap2_odd_sign */
    740     EFUN(wr_hwtune_ovr_write_val(val<0?1:0));
    741     EFUN(wr_hwtune_ovr_write_en(1));
    742     return(ERR_CODE_NONE); 
    743 }
    744 
    745 err_code_t merlin16_pcieg3_INTERNAL_get_rx_dfe2(srds_access_t *sa__, int8_t *val) {
    746     ESTM(*val = rd_dfe_2_se() ? -(rd_dfe_2_e()+rd_dfe_2_cmn()) : (rd_dfe_2_e()+rd_dfe_2_cmn()));
    747     return (ERR_CODE_NONE);
    748 }
    749 
    750 err_code_t merlin16_pcieg3_INTERNAL_set_rx_dfe3(srds_access_t *sa__, int8_t val) {
    751     if ((val > 31) || (val < -31)) {
    752       return (_error(ERR_CODE_DFE3_INVALID));  
    753     }
    754 
    755     EFUN(merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(sa__));  /* make sure uC is stopped to avoid race conditions */
    756 
    757     EFUN(wr_hwtune_ovr_write_sel(7));                   /* Write tap3 */
    758     EFUN(wr_hwtune_ovr_write_val(val));
    759     EFUN(wr_hwtune_ovr_write_en(1));
    760     return(ERR_CODE_NONE); 
    761 }
    762 
    763 err_code_t merlin16_pcieg3_INTERNAL_get_rx_dfe3(srds_access_t *sa__, int8_t *val) {
    764     ESTM(*val = rd_dfe_3_cmn());
    765     return (ERR_CODE_NONE);
    766 }
    767 
    768 err_code_t merlin16_pcieg3_INTERNAL_set_rx_dfe4(srds_access_t *sa__, int8_t val) {
    769     if ((val > 15) || (val < -15)) {
    770       return (_error(ERR_CODE_DFE4_INVALID));  
    771     }
    772 
    773     EFUN(merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(sa__));  /* make sure uC is stopped to avoid race conditions */
    774     
    775     EFUN(wr_hwtune_ovr_write_sel(8));                   /* Write tap4 */
    776     EFUN(wr_hwtune_ovr_write_val(val));
    777     EFUN(wr_hwtune_ovr_write_en(1));
    778     return(ERR_CODE_NONE); 
    779 }
    780 
    781 err_code_t merlin16_pcieg3_INTERNAL_get_rx_dfe4(srds_access_t *sa__, int8_t *val) {
    782     ESTM(*val = rd_dfe_4_cmn());
    783     return (ERR_CODE_NONE);
    784 }
    785 
    786 err_code_t merlin16_pcieg3_INTERNAL_set_rx_dfe5(srds_access_t *sa__, int8_t val) {
    787     if ((val > 15) || (val < -15)) {
    788       return (_error(ERR_CODE_DFE5_INVALID));  
    789     }
    790 
    791     EFUN(merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(sa__));  /* make sure uC is stopped to avoid race conditions */
    792     
    793     EFUN(wr_hwtune_ovr_write_sel(9));                   /* Write tap5 */
    794     EFUN(wr_hwtune_ovr_write_val(val));
    795     EFUN(wr_hwtune_ovr_write_en(1));
    796     return(ERR_CODE_NONE); 
    797 }
    798 
    799 err_code_t merlin16_pcieg3_INTERNAL_get_rx_dfe5(srds_access_t *sa__, int8_t *val) {
    800     ESTM(*val = rd_dfe_5_cmn());
    801     return (ERR_CODE_NONE);
    802 }
    803 
    804 
    805 
    806 
    807 
    808 
    809 
    810 
    811 err_code_t merlin16_pcieg3_INTERNAL_core_clkgate(srds_access_t *sa__, uint8_t enable) {
    812 
    813   if (enable) {
    814   }
    815   else {
    816   }
    817   return (ERR_CODE_NONE);
    818 }
    819 
    820 err_code_t merlin16_pcieg3_INTERNAL_lane_clkgate(srds_access_t *sa__, uint8_t enable) {
    821 
    822   if (enable) {
    823     /* Use frc/frc_val to force all RX and TX clk_vld signals to 0 */
    824         EFUN(wr_pmd_rx_clk_vld_frc_val(0x0));
    825         EFUN(wr_pmd_rx_clk_vld_frc(0x1));
    826         EFUN(wr_pmd_tx_clk_vld_frc_val(0x0));
    827         EFUN(wr_pmd_tx_clk_vld_frc(0x1));
    828 
    829     /* Use frc_on to force clkgate */
    830         EFUN(wr_ln_rx_s_clkgate_frc_on(0x1));
    831 
    832         EFUN(wr_ln_tx_s_clkgate_frc_on(0x1));
    833 
    834   }
    835   else {
    836         EFUN(wr_pmd_rx_clk_vld_frc_val(0x0));
    837         EFUN(wr_pmd_rx_clk_vld_frc(0x0));
    838         EFUN(wr_pmd_tx_clk_vld_frc_val(0x0));
    839         EFUN(wr_pmd_tx_clk_vld_frc(0x1));
    840 
    841         EFUN(wr_ln_rx_s_clkgate_frc_on(0x0));
    842 
    843         EFUN(wr_ln_tx_s_clkgate_frc_on(0x0));
    844   }
    845   return (ERR_CODE_NONE);
    846 }
    847 
    848 
    849 err_code_t merlin16_pcieg3_INTERNAL_get_osr_mode(srds_access_t *sa__, merlin16_pcieg3_osr_mode_st *imode) {
    850     merlin16_pcieg3_osr_mode_st mode;
    851 
    852      ENULL_MEMSET(&mode, 0, sizeof(merlin16_pcieg3_osr_mode_st));
    853 
    854     if(!imode) 
    855         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    856 
    857   ESTM(mode.tx = rd_tx_osr_mode());
    858   ESTM(mode.rx = rd_rx_osr_mode());
    859   mode.tx_rx = 255;
    860   *imode = mode;
    861   return (ERR_CODE_NONE);
    862 
    863 }
    864 
    865 
    866 err_code_t merlin16_pcieg3_INTERNAL_pmd_lock_status(srds_access_t *sa__, uint8_t *pmd_lock, uint8_t *pmd_lock_chg) {
    867     uint16_t rddata;
    868 #if defined(reg_rd_TLB_RX_RXDBG_PMD_RX_LOCK_STATUS)
    869     ESTM(rddata = reg_rd_TLB_RX_RXDBG_PMD_RX_LOCK_STATUS());
    870     ESTM(*pmd_lock = ex_TLB_RX_RXDBG_PMD_RX_LOCK_STATUS__dbg_pmd_rx_lock(rddata));
    871     ESTM(*pmd_lock_chg = ex_TLB_RX_RXDBG_PMD_RX_LOCK_STATUS__dbg_pmd_rx_lock_change(rddata));
    872 #else
    873     ESTM(rddata = reg_rd_TLB_RX_PMD_RX_LOCK_STATUS());
    874     ESTM(*pmd_lock = ex_TLB_RX_PMD_RX_LOCK_STATUS__pmd_rx_lock(rddata));
    875     ESTM(*pmd_lock_chg = ex_TLB_RX_PMD_RX_LOCK_STATUS__pmd_rx_lock_change(rddata));
    876 #endif
    877     return(ERR_CODE_NONE);
    878 }
    879 
    880 err_code_t merlin16_pcieg3_INTERNAL_sigdet_status(srds_access_t *sa__, uint8_t *sig_det, uint8_t *sig_det_chg) {
    881     ESTM(*sig_det     = ((rd_rx_sigdet() >> 1) & 0x1));
    882     ESTM(*sig_det_chg = (uint8_t)rd_rg_sigdet_tggl_cnt());
    883     return(ERR_CODE_NONE);
    884 }
    885 
    886 err_code_t merlin16_pcieg3_INTERNAL_pll_lock_status(srds_access_t *sa__, uint8_t *pll_lock, uint8_t *pll_lock_chg) {
    887 
    888     uint16_t rddata;
    889     uint8_t pll_fail;
    890     ESTM(rddata = reg_rdc_PLL_CAL_COM_STS_0());
    891     ESTM(*pll_lock = exc_PLL_CAL_COM_STS_0__pll_lock(rddata));
    892     ESTM(pll_fail = exc_PLL_CAL_COM_STS_0__pll_fail_stky(rddata));
    893     ESTM(*pll_lock_chg = ((*pll_lock ^ !exc_PLL_CAL_COM_STS_0__pll_lock_bar_stky(rddata)) | (*pll_lock ^ !pll_fail)));
    894     return(ERR_CODE_NONE);
    895 }
    896 
    897 err_code_t merlin16_pcieg3_INTERNAL_read_lane_state(srds_access_t *sa__, merlin16_pcieg3_lane_state_st *istate) {  
    898        
    899   merlin16_pcieg3_lane_state_st state;
    900   uint8_t ladder_range = 0;
    901 
    902   ENULL_MEMSET(&state, 0, sizeof(merlin16_pcieg3_lane_state_st));
    903 
    904   if(!istate) 
    905     return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    906 
    907   EFUN(merlin16_pcieg3_INTERNAL_pmd_lock_status(sa__,&state.rx_lock, &state.rx_lock_chg));
    908   {
    909       err_code_t err_code = 0;
    910       state.stop_state = merlin16_pcieg3_INTERNAL_stop_micro(sa__,state.rx_lock,&err_code);
    911       if(err_code) USR_PRINTF(("Unable to stop microcontroller,  following data is suspect\n"));
    912   }
    913 
    914   ESTM(state.rate_select = (rd_rate_sel()+1));
    915   ESTM(state.dsc_one_hot_0_0 = rd_dsc_state_one_hot_0());
    916   ESTM(state.dsc_one_hot_0_1 = rd_dsc_state_one_hot_0());
    917   {  merlin16_pcieg3_osr_mode_st osr_mode;
    918   ENULL_MEMSET(&osr_mode, 0, sizeof(merlin16_pcieg3_osr_mode_st));
    919   EFUN(merlin16_pcieg3_INTERNAL_get_osr_mode(sa__, &osr_mode));
    920   state.osr_mode = osr_mode;
    921   }
    922   ESTM(state.reset_state = rd_lane_dp_reset_state());
    923   EFUN(merlin16_pcieg3_INTERNAL_sigdet_status(sa__,&state.sig_det, &state.sig_det_chg));
    924   ESTM(state.rx_ppm = rd_cdr_integ_reg()/84);
    925   ESTM(state.clk90 = rd_cnt_d_minus_m1());
    926   ESTM(state.clkp1 = rd_cnt_d_minus_p1());
    927   ESTM(state.br_pd_en = rd_br_pd_en());
    928   /* drop the MSB, the result is actually valid modulo 128 */
    929   /* Also flip the sign to account for d-m1, versus m1-d */
    930   state.clk90 = state.clk90<<1;
    931   state.clk90 = -(state.clk90>>1);
    932   state.clkp1 = state.clkp1<<1;
    933   state.clkp1 = -(state.clkp1>>1);
    934   
    935   EFUN(merlin16_pcieg3_INTERNAL_get_rx_pf_main(sa__, &state.pf_main));
    936   ESTM(state.pf_hiz = rd_pf_hiz());
    937   {
    938       uint8_t rate_sel;
    939       ESTM(rate_sel = rd_rate_sel());
    940       if (rate_sel == MERLIN16_PCIEG3_GEN1) {
    941           ESTM(state.pf2_ctrl = merlin16_pcieg3_INTERNAL_gray_to_uint8(rd_pf2_lowp_ctrl_g1()));
    942       } else if (rate_sel == MERLIN16_PCIEG3_GEN2) {
    943           ESTM(state.pf2_ctrl = merlin16_pcieg3_INTERNAL_gray_to_uint8(rd_pf2_lowp_ctrl_g2()));
    944       } else {
    945           ESTM(state.pf2_ctrl = rd_pf2_lowp_ctrl());
    946       }
    947   }
    948   EFUN(merlin16_pcieg3_INTERNAL_get_rx_vga(sa__, &state.vga));
    949   ESTM(state.dc_offset = rd_dc_offset_bin());
    950   ESTM(ladder_range = rd_p1_thresh_sel());
    951   EFUN(merlin16_pcieg3_INTERNAL_get_p1_threshold(sa__, &state.p1_lvl_ctrl));         
    952   state.p1_lvl = merlin16_pcieg3_INTERNAL_ladder_setting_to_mV(sa__, state.p1_lvl_ctrl, ladder_range);
    953   state.m1_lvl = 0;
    954 
    955   EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe1(sa__, &state.dfe1));
    956   EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe2(sa__, &state.dfe2));  
    957   EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe3(sa__, &state.dfe3));  
    958   EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe4(sa__, &state.dfe4));
    959   EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe5(sa__, &state.dfe5));
    960 
    961   ESTM(state.dfe1_dcd = rd_dfe_1_e()-rd_dfe_1_o());
    962   ESTM(state.dfe2_dcd = (rd_dfe_2_se() ? -rd_dfe_2_e(): rd_dfe_2_e()) -(rd_dfe_2_so() ? -rd_dfe_2_o(): rd_dfe_2_o()));
    963   ESTM(state.pe = rd_p1_offset_evn_bin());
    964   ESTM(state.ze = rd_data_offset_evn_bin());
    965   ESTM(state.me = rd_m1_offset_evn_bin());
    966   
    967   ESTM(state.po = rd_p1_offset_odd_bin());
    968   ESTM(state.zo = rd_data_offset_odd_bin());
    969   ESTM(state.mo = rd_m1_offset_odd_bin());
    970 
    971   /* tx_ppm = register/10.84 */
    972   ESTM(state.tx_ppm = (int16_t)(((int32_t)(rd_tx_pi_integ2_reg()))*3125/32768));
    973 
    974 
    975   if (!state.stop_state) {
    976       EFUN(merlin16_pcieg3_stop_rx_adaptation(sa__, 0));
    977   } 
    978 
    979   *istate = state;
    980   return (ERR_CODE_NONE);
    981 }
    982 
    983 err_code_t merlin16_pcieg3_INTERNAL_display_lane_state_no_newline(srds_access_t *sa__) {     
    984   uint16_t lane_idx;
    985   merlin16_pcieg3_lane_state_st state;
    986 
    987 
    988 
    989   ENULL_MEMSET(&state, 0, sizeof(merlin16_pcieg3_lane_state_st));
    990 
    991   EFUN(merlin16_pcieg3_INTERNAL_read_lane_state(sa__, &state));
    992  
    993   lane_idx = merlin16_pcieg3_get_lane(sa__); 
    994   EFUN_PRINTF(("%2d ", lane_idx));
    995   EFUN_PRINTF((" %01x ",state.stop_state));
    996   EFUN_PRINTF((" GEN%1d", state.rate_select));
    997   EFUN_PRINTF((" %04X,%04X", state.dsc_one_hot_0_0, state.dsc_one_hot_0_1));
    998   EFUN_PRINTF(("   %1d,%3u", state.sig_det, state.sig_det_chg));
    999   EFUN_PRINTF(("  %1d%s", state.rx_lock, state.rx_lock_chg ? "*" : " "));
   1000   EFUN_PRINTF(("%4d ", state.rx_ppm));
   1001   EFUN_PRINTF(("  %3d ", state.clk90));
   1002   EFUN_PRINTF(("  %3d ", state.clkp1));
   1003   EFUN_PRINTF(("   %2d,%1d ", state.pf_main, state.pf2_ctrl));
   1004   EFUN_PRINTF(("  %2d ", state.vga));
   1005   EFUN_PRINTF(("%3d  ", state.dc_offset));
   1006   EFUN_PRINTF(("%3d ", state.p1_lvl));
   1007   EFUN_PRINTF(("%3d,%3d,%3d,%3d,%3d,%3d,%3d ", state.dfe1, state.dfe2, state.dfe3, state.dfe4, state.dfe5, state.dfe1_dcd, state.dfe2_dcd));
   1008   EFUN_PRINTF(("%3d,%3d,%3d,%3d,%3d,%3d  ", state.ze, state.zo, state.pe, state.po, state.me, state.mo));
   1009   EFUN_PRINTF(("  %4d ", state.tx_ppm));
   1010   
   1011   return (ERR_CODE_NONE);
   1012 }
   1013 
   1014 
   1015 err_code_t merlin16_pcieg3_INTERNAL_read_core_state(srds_access_t *sa__, merlin16_pcieg3_core_state_st *istate) {  
   1016   merlin16_pcieg3_core_state_st state;
   1017   struct merlin16_pcieg3_uc_core_config_st core_cfg;
   1018 
   1019   ENULL_MEMSET(&state, 0, sizeof(merlin16_pcieg3_core_state_st));
   1020   ENULL_MEMSET(&core_cfg, 0, sizeof(struct merlin16_pcieg3_uc_core_config_st));
   1021 
   1022   if(!istate) 
   1023     return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
   1024   /* pllpon_mux is read in case the rescal value is overriden. */
   1025   ESTM(state.rescal = rdc_pllpon_mux());
   1026   ESTM(state.core_reset           = rdc_core_dp_reset_state());
   1027   ESTM(state.uc_active            = rdc_uc_active());
   1028   ESTM(state.comclk_mhz           = rdc_heartbeat_count_1us());   
   1029   ESTM(state.ucode_version        = rdcv_common_ucode_version()); 
   1030   ESTM(state.ucode_minor_version  = rdcv_common_ucode_minor_version());
   1031   ESTM(state.afe_hardware_version = rdcv_afe_hardware_version());
   1032   ESTM(state.temp_idx             = rdcv_temp_idx());
   1033   {  int16_t                           die_temp = 0;
   1034      EFUN(merlin16_pcieg3_read_die_temperature(sa__, &die_temp));
   1035      state.die_temp               =    die_temp;
   1036   }
   1037   ESTM(state.avg_tmon             = _bin_to_degC(rdcv_avg_tmon_reg13bit()>>3));
   1038   state.vco_rate_mhz            = (uint16_t)core_cfg.vco_rate_in_Mhz;
   1039   ESTM(state.analog_vco_range     = rdc_pll_range());   
   1040   EFUN(merlin16_pcieg3_INTERNAL_pll_lock_status(sa__, &state.pll_lock, &state.pll_lock_chg));
   1041   ESTM(state.core_status          = rdcv_status_byte());
   1042   ESTM(state.rate_select = (rd_rate_sel()+1));
   1043 
   1044   *istate = state;
   1045   return (ERR_CODE_NONE);
   1046 }
   1047 
   1048 
   1049 err_code_t merlin16_pcieg3_INTERNAL_display_core_state_no_newline(srds_access_t *sa__) {
   1050   merlin16_pcieg3_core_state_st state;
   1051     ENULL_MEMSET(&state     , 0, sizeof(state     ));
   1052   EFUN(merlin16_pcieg3_INTERNAL_read_core_state(sa__, &state));
   1053 
   1054 	if ((state.avg_tmon<-50)||(state.avg_tmon>135)) {
   1055           EFUN_PRINTF(("\n*** WARNING: Core die temperature (LIVE_TEMP) out of bounds -50C to 130C\n"));
   1056 	}
   1057 	if ((state.rescal < 6) || (state.rescal > 13)) {
   1058           EFUN_PRINTF(("\n*** WARNING: RESCAL value is out of bounds 6 to 13\n"));
   1059 	}
   1060 
   1061     EFUN_PRINTF((" %02d "              ,  merlin16_pcieg3_get_core(sa__)));
   1062     EFUN_PRINTF((" %02x  "             ,  state.core_status));
   1063     EFUN_PRINTF(("    %1d     "        ,  state.pll_pwrdn));
   1064     EFUN_PRINTF((" %3d.%2dMHz"         , (state.comclk_mhz/4),((state.comclk_mhz%4)*25)));    /* comclk in Mhz = heartbeat_count_1us / 4 */
   1065     EFUN_PRINTF(("   %4X_%02X "        ,  state.ucode_version, state.ucode_minor_version));
   1066     EFUN_PRINTF(("    0x%02x   "       ,  state.afe_hardware_version));
   1067     EFUN_PRINTF(("   %3dC   "          ,  state.die_temp));
   1068     EFUN_PRINTF(("   (%02d)%3dC "      ,  state.temp_idx, state.avg_tmon));
   1069     EFUN_PRINTF(("   0x%02x  "         ,  state.rescal));
   1070     EFUN_PRINTF(("  GEN%d "            ,  state.rate_select));
   1071     EFUN_PRINTF(("    %03d       "     ,  state.analog_vco_range));
   1072     EFUN_PRINTF(("     %01d%s  "       ,  state.pll_lock, state.pll_lock_chg ? "*" : " "));
   1073 
   1074     return (ERR_CODE_NONE);
   1075   }
   1076 
   1077 
   1078 
   1079 err_code_t merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(srds_access_t *sa__) {
   1080 
   1081   uint8_t is_micro_stopped;
   1082   ESTM(is_micro_stopped = rdv_usr_sts_micro_stopped());
   1083   if (!is_micro_stopped) {
   1084       return(_error(ERR_CODE_UC_NOT_STOPPED));
   1085   } else {
   1086       return(ERR_CODE_NONE);
   1087   }
   1088 }
   1089 
   1090 err_code_t merlin16_pcieg3_INTERNAL_calc_patt_gen_mode_sel(uint8_t *mode_sel, uint8_t *zero_pad_len, uint8_t patt_length) {
   1091 
   1092   if(!mode_sel) {
   1093     return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
   1094   }
   1095   if(!zero_pad_len) {
   1096     return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
   1097   }
   1098 
   1099   /* Select the correct Pattern generator Mode depending on Pattern length */
   1100   if (!(140 % patt_length)) {
   1101     *mode_sel = 6;
   1102     *zero_pad_len = 100;
   1103   }
   1104   else if (!(160 % patt_length)) {
   1105     *mode_sel = 5;
   1106     *zero_pad_len = 80;
   1107   }
   1108   else if (!(180 % patt_length)) {
   1109     *mode_sel = 4;
   1110     *zero_pad_len = 60;
   1111   }
   1112   else if (!(200 % patt_length)) {
   1113     *mode_sel = 3;
   1114     *zero_pad_len = 40;
   1115   }
   1116   else if (!(220 % patt_length)) {
   1117     *mode_sel = 2;
   1118     *zero_pad_len = 20;
   1119   }
   1120   else if (!(240 % patt_length)) {
   1121     *mode_sel = 1;
   1122     *zero_pad_len = 0;
   1123   } else {
   1124     EFUN_PRINTF(("ERROR: Unsupported Pattern Length\n"));
   1125     return (_error(ERR_CODE_CFG_PATT_INVALID_PATT_LENGTH));
   1126   }
   1127   return(ERR_CODE_NONE);
   1128 }
   1129 
   1130 
   1131 err_code_t merlin16_pcieg3_INTERNAL_print_uc_dsc_error(srds_access_t *sa__, enum srds_pmd_uc_cmd_enum cmd) {
   1132     uint32_t supp_info;
   1133 
   1134     ESTM(supp_info = (rd_uc_dsc_supp_info()) & 0xFF);
   1135     switch (SUPP_INFO_TO_ERROR_CODE(supp_info)) {
   1136       case UC_CMD_ERROR_INVALID_COMMAND:
   1137         ESTM_PRINTF(("ERROR : UC reported invalid command %d.  (other_info = 0x%X)\n",
   1138                      cmd, SUPP_INFO_TO_OTHER_INFO(supp_info)));
   1139         break;
   1140       case UC_CMD_ERROR_BUSY:
   1141         ESTM_PRINTF(("ERROR : UC reported busy for command %d.  (other_info = 0x%X)\n",
   1142                      cmd, SUPP_INFO_TO_OTHER_INFO(supp_info)));
   1143         break;
   1144       case UC_CMD_ERROR_GET_EYE_SAMPLE_ERROR:
   1145         ESTM_PRINTF(("ERROR : UC reported error in getting eye sample.  (command %d, other_info = 0x%X)\n",
   1146                      cmd, SUPP_INFO_TO_OTHER_INFO(supp_info)));
   1147         break;
   1148       case UC_CMD_ERROR_PRBS_NOT_LOCKED:
   1149         ESTM_PRINTF(("ERROR : UC reported PRBS not locked.  (command %d, other_info = 0x%X)\n",
   1150                      cmd, SUPP_INFO_TO_OTHER_INFO(supp_info)));
   1151         break;
   1152       case UC_CMD_ERROR_COMMAND_IN_PROGRESS:
   1153         ESTM_PRINTF(("ERROR : UC reported command already in progress.  (command %d, other_info = 0x%X)\n",
   1154                      cmd, SUPP_INFO_TO_OTHER_INFO(supp_info)));
   1155         break;
   1156       case UC_CMD_ERROR_INVALID_MODE:
   1157         ESTM_PRINTF(("ERROR : UC reported invalid mode for command %d.  (other_info = 0x%X)\n",
   1158                      cmd, SUPP_INFO_TO_OTHER_INFO(supp_info)));
   1159         break;
   1160       default:
   1161         ESTM_PRINTF(("ERROR : UC reported unknown error 0x%X for command %d.  (other_info = 0x%X)\n",
   1162                      SUPP_INFO_TO_ERROR_CODE(supp_info), cmd, SUPP_INFO_TO_OTHER_INFO(supp_info)));
   1163     }
   1164     /* Cleanup cmd register */
   1165     EFUN(reg_wr_DSC_A_DSC_UC_CTRL(0x80));
   1166     EFUN(wr_uc_dsc_data(0));
   1167 
   1168     return(ERR_CODE_NONE);
   1169 }
   1170  
   1171 /******************************************/
   1172 /*  Serdes Register field Poll functions  */
   1173 /******************************************/
   1174 
   1175 #ifndef CUSTOM_REG_POLLING
   1176 
   1177 /* poll for microcontroller to populate the dsc_data register */
   1178 err_code_t merlin16_pcieg3_INTERNAL_poll_diag_done(srds_access_t *sa__, uint16_t *status, uint32_t timeout_ms) {
   1179  uint8_t loop;
   1180 
   1181  if(!status) {
   1182      return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
   1183   }
   1184 
   1185  for(loop=0;loop < 100; loop++) {
   1186      ESTM(*status=rdv_usr_diag_status());
   1187 
   1188      if((*status & 0x8000) > 0) {
   1189          return(ERR_CODE_NONE);
   1190      }
   1191      if(loop>10) {
   1192          EFUN(USR_DELAY_US(10*timeout_ms));
   1193      }
   1194  }
   1195  return(_error(ERR_CODE_DIAG_TIMEOUT));
   1196 }
   1197 
   1198 /** Poll for field "uc_dsc_ready_for_cmd" = 1 [Return Val => Error_code (0 = Polling Pass)] */
   1199 err_code_t merlin16_pcieg3_INTERNAL_poll_uc_dsc_ready_for_cmd_equals_1(srds_access_t *sa__, uint32_t timeout_ms, enum srds_pmd_uc_cmd_enum cmd) {
   1200     /* read quickly for 10 tries */
   1201     uint16_t loop;
   1202 
   1203     for (loop = 0; loop < 100; loop++) {
   1204         uint16_t rddata;
   1205         ESTM(rddata = reg_rd_DSC_A_DSC_UC_CTRL());
   1206         if (rddata & 0x0080) {    /* bit 7 is uc_dsc_ready_for_cmd */
   1207             if (rddata & 0x0040) {  /* bit 6 is uc_dsc_error_found   */
   1208                 EFUN(merlin16_pcieg3_INTERNAL_print_uc_dsc_error(sa__, cmd));
   1209                 return(_error(ERR_CODE_UC_CMD_RETURN_ERROR));
   1210             }
   1211             return (ERR_CODE_NONE);
   1212         }
   1213         if(loop>10) {
   1214             EFUN(USR_DELAY_US(10*timeout_ms));
   1215         }
   1216     }
   1217   EFUN_PRINTF(("ERROR : DSC ready for command is not working, applying workaround and getting debug info !\n"));
   1218   DISP(rd_uc_dsc_supp_info());
   1219   DISP(rd_uc_dsc_gp_uc_req());
   1220   DISP(rd_dsc_state());
   1221   ESTM_PRINTF(("Uc Core Status Byte = 0x%x\n",rdcv_status_byte()));
   1222   DISP(rdv_usr_sts_micro_stopped());
   1223   /* DISP(rdv_stop_graceful_trigger()); */
   1224   /* artifically terminate the command to re-enable the command interface */
   1225   EFUN(wr_uc_dsc_ready_for_cmd(0x1));
   1226   return (_error(ERR_CODE_POLLING_TIMEOUT));          /* Error Code for polling timeout */
   1227 }
   1228 
   1229 /* Poll for field "dsc_state" = DSC_STATE_UC_TUNE [Return Val => Error_code (0 = Polling Pass)] */
   1230 err_code_t merlin16_pcieg3_INTERNAL_poll_dsc_state_equals_uc_tune(srds_access_t *sa__, uint32_t timeout_ms) {
   1231   uint16_t loop;
   1232   uint16_t dsc_state;
   1233   /* poll 10 times to avoid longer delays later */
   1234   for (loop = 0; loop < 100; loop++) {
   1235     ESTM(dsc_state = rd_dsc_state());
   1236     if (dsc_state == DSC_STATE_UC_TUNE) {
   1237       return (ERR_CODE_NONE);
   1238     }
   1239     if(loop>10) {
   1240         EFUN(USR_DELAY_US(10*timeout_ms));
   1241     }
   1242   }
   1243   ESTM_PRINTF(("DSC_STATE = %d\n", rd_dsc_state()));
   1244   return (_error(ERR_CODE_POLLING_TIMEOUT));          /* Error Code for polling timeout */
   1245 }
   1246 
   1247 
   1248 
   1249 
   1250 /* Poll for field "micro_ra_initdone" = 1 [Return Val => Error_code (0 = Polling Pass)] */
   1251 err_code_t merlin16_pcieg3_INTERNAL_poll_micro_ra_initdone(srds_access_t *sa__, uint32_t timeout_ms) {
   1252   uint16_t loop;
   1253 
   1254   uint8_t result;
   1255   for (loop = 0; loop <= 100; loop++) {
   1256     ESTM(result = rdc_micro_ra_initdone());
   1257     if (result) {
   1258       return (ERR_CODE_NONE);
   1259     }
   1260     EFUN(USR_DELAY_US(10*timeout_ms));
   1261   }
   1262   return (_error(ERR_CODE_POLLING_TIMEOUT));          /* Error Code for polling timeout */
   1263 }
   1264 
   1265 #endif /* CUSTOM_REG_POLLING */
   1266 
   1267 
   1268 
   1269 err_code_t merlin16_pcieg3_INTERNAL_rdblk_callback(void *arg, uint8_t byte_count, uint16_t data) {
   1270     merlin16_pcieg3_INTERNAL_rdblk_callback_arg_t * const cast_arg = (merlin16_pcieg3_INTERNAL_rdblk_callback_arg_t *)arg;
   1271     *(cast_arg->mem_ptr + get_endian_offset(cast_arg->mem_ptr)) = data & 0xFF;
   1272     cast_arg->mem_ptr++;
   1273     if (byte_count == 2) {
   1274         *(cast_arg->mem_ptr + get_endian_offset(cast_arg->mem_ptr)) = data >> 8;
   1275         cast_arg->mem_ptr++;
   1276     }
   1277     return (ERR_CODE_NONE);
   1278 }
   1279 
   1280 err_code_t merlin16_pcieg3_INTERNAL_rdblk_uc_generic_ram(srds_access_t *sa__,
   1281                                                 uint32_t block_addr,
   1282                                                 uint16_t block_size,
   1283                                                 uint16_t start_offset,
   1284                                                 uint16_t cnt,
   1285                                                 void *arg,
   1286                                                 err_code_t (*callback)(void *, uint8_t, uint16_t)) {
   1287     uint32_t read_val = 0;
   1288     uint8_t defecit = 0;
   1289     uint32_t addr = block_addr + start_offset;
   1290     
   1291     if (cnt == 0) {
   1292         return (ERR_CODE_NONE);
   1293     }
   1294 
   1295     /* Check for bad start offset and block size. */
   1296     if (start_offset >= block_size) {
   1297         return (ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1298     }
   1299 
   1300     while (cnt > 0) {
   1301         /* Determine how many bytes to read before wrapping back to start of block. */
   1302         uint16_t block_cnt = SRDS_MIN(cnt, block_addr + block_size - addr);
   1303         cnt -= block_cnt;
   1304 
   1305             /* Set up the word reads. */
   1306             EFUN(wrc_micro_autoinc_rdaddr_en(1));
   1307             EFUN(wrc_micro_ra_rddatasize(0x1));                     /* Select 16bit read datasize */
   1308             EFUN(wrc_micro_ra_rdaddr_msw(addr >> 16));              /* Upper 16bits of RAM address to be read */
   1309             EFUN(wrc_micro_ra_rdaddr_lsw(addr & 0xFFFE));           /* Lower 16bits of RAM address to be read */
   1310 
   1311             /* Read the leading byte, if starting at an odd address. */
   1312             if ((addr & 1) == 1) {
   1313                 ESTM(read_val |= ((rdc_micro_ra_rddata_lsw() >> 8) << defecit));
   1314                 if (defecit == 8) {
   1315                     EFUN(callback(arg, 2, (uint16_t)read_val));
   1316                     read_val = 0;
   1317                 }
   1318                 /* We just read a byte.  This toggles the defecit from 0 to 8 or from 8 to 0. */
   1319                 defecit ^= 8;
   1320                 --block_cnt;
   1321             }
   1322 
   1323             /* Read the whole words, and call the callback with two bytes at a time. */
   1324             while (block_cnt >= 2) {
   1325                 ESTM(read_val |= (rdc_micro_ra_rddata_lsw() << defecit));
   1326                 EFUN(callback(arg, 2, (uint16_t)read_val));
   1327                 read_val >>= 16;
   1328                 /* We just read two bytes.  This preserves whatever defecit (8 or 0) is there. */
   1329                 block_cnt -= 2;
   1330             }
   1331 
   1332             /* Read the trailing byte, if leftover after reading whole words. */
   1333             if (block_cnt > 0) {
   1334                 ESTM(read_val |= ((rdc_micro_ra_rddata_lsw() & 0xFF) << defecit));
   1335                 if (defecit == 8) {
   1336                     EFUN(callback(arg, 2, (uint16_t)read_val));
   1337                     read_val = 0;
   1338                 }
   1339                 /* We just read a byte.  This toggles the defecit from 0 to 8 or from 8 to 0. */
   1340                 defecit ^= 8;
   1341             }
   1342         addr = block_addr;
   1343     }
   1344 
   1345     /* If a final byte is left behind, then call the callback with it. */
   1346     if (defecit > 0) {
   1347         EFUN(callback(arg, 1, (uint16_t)read_val));
   1348     }
   1349 
   1350     return(ERR_CODE_NONE);
   1351 }
   1352 
   1353 err_code_t merlin16_pcieg3_INTERNAL_rdblk_uc_generic_ram_descending(srds_access_t *sa__,
   1354                                                            uint32_t block_addr,
   1355                                                            uint16_t block_size,
   1356                                                            uint16_t start_offset,
   1357                                                            uint16_t cnt,
   1358                                                            void *arg,
   1359                                                            err_code_t (*callback)(void *, uint8_t, uint16_t)) {
   1360     uint32_t read_val = 0;
   1361     uint8_t defecit = 0;
   1362     uint32_t addr = block_addr + start_offset;
   1363     uint16_t configured_addr_msw = (addr >> 16) + 1;
   1364     
   1365     if (cnt == 0) {
   1366         return (ERR_CODE_NONE);
   1367     }
   1368 
   1369     /* Check for bad start offset and block size. */
   1370     if (start_offset >= block_size) {
   1371         return (ERR_CODE_BAD_PTR_OR_INVALID_INPUT);
   1372     }
   1373 
   1374     EFUN(wrc_micro_autoinc_rdaddr_en(0));
   1375     EFUN(wrc_micro_ra_rddatasize(0x1));                         /* Select 16bit read datasize */
   1376     
   1377     while (cnt > 0) {
   1378         /* Determine how many bytes to read before wrapping back to end of block. */
   1379         uint16_t block_cnt = SRDS_MIN(cnt, start_offset+1);
   1380         cnt -= block_cnt;
   1381 
   1382         while (block_cnt > 0) {
   1383             const uint16_t addr_msw = addr >> 16;
   1384             uint16_t read_val2;
   1385             if (addr_msw != configured_addr_msw) {
   1386                 EFUN(wrc_micro_ra_rdaddr_msw(addr_msw));        /* Upper 16bits of RAM address to be read */
   1387                 configured_addr_msw = addr_msw;
   1388             }
   1389             
   1390             EFUN(wrc_micro_ra_rdaddr_lsw(addr & 0xFFFE));       /* Lower 16bits of RAM address to be read */
   1391             ESTM(read_val2 = rdc_micro_ra_rddata_lsw());
   1392 
   1393             if (((addr & 1) == 1) && (block_cnt >= 2)) {
   1394                 /* Reading two bytes.  Since we're reading in descending address order, they
   1395                  * will be reversed before they are sent out. */
   1396                 read_val |= ((((read_val2 & 0xFF) << 8) | (read_val2 >> 8)) << defecit);
   1397                 EFUN(callback(arg, 2, (uint16_t)read_val));
   1398                 read_val >>= 16;
   1399                 /* We just read two bytes.  This preserves whatever defecit (8 or 0) is there. */
   1400                 block_cnt -= 2;
   1401                 addr -= 2;
   1402             } else {
   1403                 if ((addr & 1) == 1) {
   1404                     /* Reading upper byte of word. */
   1405                     read_val |= ((read_val2 >> 8) << defecit);
   1406                 } else {
   1407                     /* Reading lower byte of word. */
   1408                     read_val |= ((read_val2 & 0xFF) << defecit);
   1409                 }
   1410                 if (defecit == 8) {
   1411                     EFUN(callback(arg, 2, (uint16_t)read_val));
   1412                     read_val = 0;
   1413                 }
   1414                 /* We just read a byte.  This toggles the defecit from 0 to 8 or from 8 to 0. */
   1415                 defecit ^= 8;
   1416                 --block_cnt;
   1417                 --addr;
   1418             }
   1419         }
   1420         
   1421         addr = block_addr + block_size - 1;
   1422         start_offset = block_size - 1;
   1423     }
   1424 
   1425     /* If a final byte is left behind, then call the callback with it. */
   1426     if (defecit > 0) {
   1427         EFUN(callback(arg, 1, (uint16_t)read_val));
   1428     }
   1429 
   1430     return(ERR_CODE_NONE);
   1431 }
   1432 
   1433 uint8_t merlin16_pcieg3_INTERNAL_grp_idx_from_lane(uint8_t lane) {
   1434     return(0);
   1435 }
   1436 
   1437