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

tdm_td3_cmn.c (18547B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  * $All Rights Reserved.$
      7  *
      8  * TDM chip-specific common facility functions
      9  */
     10 #ifdef _TDM_STANDALONE
     11 	#include <tdm_top.h>
     12 #else
     13 	#include <soc/tdm/core/tdm_top.h>
     14 #endif
     15 
     16 
     17 /**
     18 @name: tdm_td3_cmn_chk_port_is_fp
     19 @param:
     20 @desc: Return BOOL_TRUE if given port is a front panel port,
     21        otherwise return BOOL_FALSE.
     22  */
     23 int
     24 tdm_td3_cmn_chk_port_is_fp(tdm_mod_t *_tdm, int port_token)
     25 {
     26     /* return (tdm_cmn_chk_port_is_fp(_tdm, port_token)); */
     27     return ((port_token >= _tdm->_chip_data.soc_pkg.soc_vars.fp_port_lo &&
     28              port_token <= _tdm->_chip_data.soc_pkg.soc_vars.fp_port_hi) ?
     29             BOOL_TRUE : BOOL_FALSE);
     30 }
     31 
     32 
     33 /**
     34 @name: tdm_td3_cmn_chk_port_is_lr
     35 @param:
     36 @desc: Return BOOL_TRUE if given port is a linerate port,
     37        otherwise return BOOL_FALSE.
     38  */
     39 int
     40 tdm_td3_cmn_chk_port_is_lr(tdm_mod_t *_tdm, int port_token)
     41 {
     42     /* return (tdm_cmn_chk_port_is_lr(_tdm, port_token)); */
     43     int port_state;
     44     port_state = tdm_td3_cmn_get_port_state(_tdm, port_token);
     45     return ((port_state == PORT_STATE__LINERATE    ||
     46              port_state == PORT_STATE__LINERATE_HG) ?
     47             BOOL_TRUE : BOOL_FALSE);
     48 }
     49 
     50 
     51 /**
     52 @name: tdm_td3_cmn_chk_port_is_os
     53 @param:
     54 @desc: Return BOOL_TRUE if given port is an oversubscript port,
     55        otherwise return BOOL_FALSE.
     56  */
     57 int
     58 tdm_td3_cmn_chk_port_is_os(tdm_mod_t *_tdm, int port_token)
     59 {
     60     /* return (tdm_cmn_chk_port_is_os(_tdm, port_token)); */
     61     int port_state;
     62     port_state = tdm_td3_cmn_get_port_state(_tdm, port_token);
     63     return ((port_state == PORT_STATE__OVERSUB    ||
     64              port_state == PORT_STATE__OVERSUB_HG) ?
     65             BOOL_TRUE : BOOL_FALSE);
     66 }
     67 
     68 
     69 /**
     70 @name: tdm_td3_cmn_chk_port_is_mgmt
     71 @param:
     72 @desc: Return BOOL_TRUE if given port is a management port,
     73        otherwise return BOOL_FALSE.
     74  */
     75 int
     76 tdm_td3_cmn_chk_port_is_mgmt(tdm_mod_t *_tdm, int port_token)
     77 {
     78     /* return (tdm_cmn_chk_port_is_os(_tdm, port_token)); */
     79     int port_state;
     80     port_state = tdm_td3_cmn_get_port_state(_tdm, port_token);
     81     return ((port_state == PORT_STATE__MANAGEMENT) ?
     82             BOOL_TRUE : BOOL_FALSE);
     83 }
     84 
     85 
     86 /**
     87 @name: tdm_td3_cmn_chk_port_is_hg
     88 @param:
     89 @desc: Return BOOL_TRUE if given port is a higig/higig2 port,
     90        otherwise return BOOL_FALSE.
     91  */
     92 int
     93 tdm_td3_cmn_chk_port_is_hg(tdm_mod_t *_tdm, int port_token)
     94 {
     95     /* return (tdm_cmn_chk_port_is_hg(_tdm, port_token)); */
     96     int port_state;
     97     port_state = tdm_td3_cmn_get_port_state(_tdm, port_token);
     98     return ((port_state == PORT_STATE__LINERATE_HG ||
     99              port_state == PORT_STATE__OVERSUB_HG) ?
    100             BOOL_TRUE : BOOL_FALSE);
    101 }
    102 
    103 
    104 /**
    105 @name: tdm_td3_cmn_get_port_pm
    106 @param:
    107 
    108 Return Port Macro number of the given port
    109  */
    110 int
    111 tdm_td3_cmn_get_port_pm(tdm_mod_t *_tdm, int port_token)
    112 {
    113     int port_pm;
    114 
    115     if (_tdm->_chip_data.soc_pkg.pmap_num_lanes > 0 &&
    116         port_token >=_tdm->_chip_data.soc_pkg.soc_vars.fp_port_lo &&
    117         port_token <=_tdm->_chip_data.soc_pkg.soc_vars.fp_port_hi) {
    118         port_pm = (port_token - 1) / _tdm->_chip_data.soc_pkg.pmap_num_lanes;
    119     } else {
    120         port_pm = _tdm->_chip_data.soc_pkg.pm_num_phy_modules;
    121     }
    122 
    123     return (port_pm % TD3_NUM_PM_MOD);
    124 }
    125 
    126 
    127 /**
    128 @name: tdm_td3_cmn_get_port_speed
    129 @param:
    130 
    131 Return port speed of the given port
    132  */
    133 int
    134 tdm_td3_cmn_get_port_speed(tdm_mod_t *_tdm, int port_token)
    135 {
    136     /* return (tdm_cmn_get_port_speed(_tdm, port_token)); */
    137     if (tdm_td3_cmn_chk_port_is_fp(_tdm, port_token) == BOOL_TRUE) {
    138         return (_tdm->_chip_data.soc_pkg.speed[port_token]);
    139     } else {
    140         return 0;
    141     }
    142 }
    143 
    144 
    145 /**
    146 @name: tdm_td3_cmn_get_port_speed_eth
    147 @param:
    148 
    149 Return port speed in ethernet mode. This converts HiGig speed to ethernet.
    150  */
    151 int
    152 tdm_td3_cmn_get_port_speed_eth(tdm_mod_t *_tdm, int port_token)
    153 {
    154     /* return (tdm_cmn_get_port_speed_eth(_tdm, port_token)); */
    155     int port_speed, port_speed_eth;
    156 
    157     port_speed = tdm_td3_cmn_get_port_speed(_tdm, port_token);
    158     switch(port_speed) {
    159         case SPEED_1G:
    160         case SPEED_1p25G:
    161         case SPEED_2p5G:
    162         case SPEED_5G:
    163             port_speed_eth = port_speed;
    164             break;
    165         case SPEED_10G:
    166         case SPEED_10G_DUAL:
    167         case SPEED_10G_XAUI:
    168         case SPEED_11G:
    169             port_speed_eth = SPEED_10G;
    170             break;
    171         case SPEED_12p5G:
    172             port_speed_eth = SPEED_12p5G;
    173             break;
    174         case SPEED_20G:
    175         case SPEED_21G:
    176         case SPEED_21G_DUAL:
    177             port_speed_eth = SPEED_20G;
    178             break;
    179         case SPEED_25G:
    180         case SPEED_27G:
    181             port_speed_eth = SPEED_25G;
    182             break;
    183         case SPEED_40G:
    184         case SPEED_42G:
    185         case SPEED_42G_HG2:
    186             port_speed_eth = SPEED_40G;
    187             break;
    188         case SPEED_50G:
    189         case SPEED_53G:
    190             port_speed_eth = SPEED_50G;
    191             break;
    192         case SPEED_100G:
    193         case SPEED_106G:
    194             port_speed_eth = SPEED_100G;
    195             break;
    196         case SPEED_120G:
    197         case SPEED_127G:
    198             port_speed_eth = SPEED_120G;
    199             break;
    200         case SPEED_200G:
    201             port_speed_eth = SPEED_200G;
    202             break;
    203         case SPEED_400G:
    204             port_speed_eth = SPEED_400G;
    205             break;
    206         default:
    207             port_speed_eth = 0;
    208             break;
    209     }
    210 
    211     return port_speed_eth;
    212 }
    213 
    214 
    215 /**
    216 @name: tdm_td3_cmn_get_port_state
    217 @param:
    218 
    219 Return port state of the given port
    220  */
    221 int
    222 tdm_td3_cmn_get_port_state(tdm_mod_t *_tdm, int port_token)
    223 {
    224     if (port_token >= _tdm->_chip_data.soc_pkg.soc_vars.fp_port_lo &&
    225         port_token <= _tdm->_chip_data.soc_pkg.soc_vars.fp_port_hi) {
    226         return (_tdm->_chip_data.soc_pkg.state[port_token-1]);
    227     }
    228 
    229     return (PORT_STATE__DISABLED);
    230 }
    231 
    232 
    233 /**
    234 @name: tdm_td3_cmn_get_speed_lanes
    235 @param:
    236 
    237 Return the number of lanes required by the given speed
    238 (Chip-Specific)
    239  */
    240 int
    241 tdm_td3_cmn_get_speed_lanes(int port_speed)
    242 {
    243     int lanes = 0;
    244 
    245     switch(port_speed){
    246         case SPEED_1G:  case SPEED_2p5G:
    247         case SPEED_10G: case SPEED_11G:
    248         case SPEED_20G: case SPEED_21G:
    249         case SPEED_25G: case SPEED_27G:
    250             lanes = 1;
    251             break;
    252         case SPEED_40G: case SPEED_42G: case SPEED_42G_HG2:
    253         case SPEED_50G: case SPEED_53G:
    254             lanes = 2;
    255             break;
    256         case SPEED_100G: case SPEED_106G:
    257             lanes = 4;
    258             break;
    259         default:
    260             break;
    261     }
    262 
    263     return (lanes);
    264 }
    265 
    266 
    267 /**
    268 @name: tdm_td3_cmn_get_speed_slots
    269 @param:
    270 
    271 Return the number of slots (2.5G per slot) of the given speed
    272 (Chip-Specific)
    273  */
    274 int 
    275 tdm_td3_cmn_get_speed_slots(int port_speed)
    276 {
    277     int slot_num=0;
    278 
    279     switch (port_speed) {
    280         case SPEED_1G:  case SPEED_2p5G:
    281             slot_num = 1;
    282             break;
    283         case SPEED_10G: case SPEED_11G:
    284             slot_num = 4;  
    285             break;
    286         case SPEED_20G: case SPEED_21G:
    287             slot_num = 8;  
    288             break;
    289         case SPEED_25G: case SPEED_27G:
    290             slot_num = 10;  
    291             break;
    292         case SPEED_40G: case SPEED_42G: case SPEED_42G_HG2:
    293             slot_num = 16;  
    294             break;
    295         case SPEED_50G: case SPEED_53G:
    296             slot_num = 20;  
    297             break;
    298         case SPEED_100G: case SPEED_106G:
    299             slot_num = 40; 
    300             break;
    301         default:
    302             TDM_ERROR4("%s, %s -- %dM (%dG)\n",
    303                        "[Port Speed]",
    304                        "invalid port speed",
    305                        port_speed, port_speed/1000);
    306             break;
    307     }
    308 
    309     return (slot_num);
    310 }
    311 
    312 
    313 /**
    314 @name: tdm_td3_cmn_get_port_slots
    315 @param:
    316  */
    317 int
    318 tdm_td3_cmn_get_port_slots(tdm_mod_t *_tdm, int port_token)
    319 {
    320     /* return (tdm_cmn_get_port_slots(_tdm, port_token)); */
    321     int port_slots, port_speed;
    322 
    323     port_speed = tdm_td3_cmn_get_port_speed_eth(_tdm, port_token);
    324     port_slots = tdm_td3_cmn_get_speed_slots(port_speed);
    325 
    326     return port_slots;
    327 }
    328 
    329 
    330 /**
    331 @name: tdm_td3_cmn_get_pipe_port_range
    332 @param:
    333 
    334 Return physical port number range of the given pipe
    335  */
    336 void 
    337 tdm_td3_cmn_get_pipe_port_range(int cal_id, int *phy_lo, int *phy_hi)
    338 {
    339     int prt_lo = 0, prt_hi = 0;
    340 
    341     switch(cal_id){
    342         case 0: prt_lo = TD3_CAL_0_PORT_LO; prt_hi = TD3_CAL_0_PORT_HI; break;
    343         case 1: prt_lo = TD3_CAL_1_PORT_LO; prt_hi = TD3_CAL_1_PORT_HI; break;
    344         case 2: prt_lo = TD3_CAL_2_PORT_LO; prt_hi = TD3_CAL_2_PORT_HI; break;
    345         case 3: prt_lo = TD3_CAL_3_PORT_LO; prt_hi = TD3_CAL_3_PORT_HI; break;
    346         case 4: prt_lo = TD3_CAL_4_PORT_LO; prt_hi = TD3_CAL_4_PORT_HI; break;
    347         case 5: prt_lo = TD3_CAL_5_PORT_LO; prt_hi = TD3_CAL_5_PORT_HI; break;
    348         case 6: prt_lo = TD3_CAL_6_PORT_LO; prt_hi = TD3_CAL_6_PORT_HI; break;
    349         case 7: prt_lo = TD3_CAL_7_PORT_LO; prt_hi = TD3_CAL_7_PORT_HI; break;
    350         default: break;
    351     }
    352     if (phy_lo != NULL && phy_hi != NULL) {
    353         *phy_lo = prt_lo;
    354         *phy_hi = prt_hi;
    355     }
    356 }
    357 
    358 
    359 /**
    360 @name: tdm_td3_cmn_get_pipe_port_lo_hi
    361 @param:
    362 
    363 Return physical port number range of the current pipe
    364  */
    365 void
    366 tdm_td3_cmn_get_pipe_port_lo_hi(tdm_mod_t *_tdm, int *phy_lo, int *phy_hi)
    367 {
    368     tdm_td3_cmn_get_pipe_port_range(_tdm->_core_data.vars_pkg.cal_id,
    369                                     phy_lo, phy_hi);
    370 }
    371 
    372 
    373 /**
    374 @name: tdm_td3_cmn_get_pipe_pm_lo_hi
    375 @param:
    376 
    377 Return physical port number range of the given pipe
    378  */
    379 void
    380 tdm_td3_cmn_get_pipe_pm_lo_hi(tdm_mod_t *_tdm, int *pm_lo, int *pm_hi)
    381 {
    382     int prt_lo = 0, prt_hi = 0;
    383 
    384     if (pm_lo != NULL && pm_hi != NULL) {
    385         tdm_td3_cmn_get_pipe_port_lo_hi(_tdm, &prt_lo, &prt_hi);
    386         *pm_lo = tdm_td3_cmn_get_port_pm(_tdm, prt_lo);
    387         *pm_hi = tdm_td3_cmn_get_port_pm(_tdm, prt_hi);
    388     }
    389 }
    390 
    391 
    392 /**
    393 @name: tdm_td3_cmn_get_pipe_ethernet
    394 @param:
    395 
    396 Return BOOL_TRUE if the given pipe has traffic entirely Ethernet;
    397 otherwise, return BOOL_FALSE.
    398  */
    399 int
    400 tdm_td3_cmn_get_pipe_ethernet(tdm_mod_t *_tdm, int cal_id)
    401 {
    402     int port, phy_lo, phy_hi;
    403 
    404     tdm_td3_cmn_get_pipe_port_range(cal_id, &phy_lo, &phy_hi);
    405     for (port = phy_lo; port <= phy_hi; port++) {
    406         if (BOOL_TRUE == tdm_td3_cmn_chk_port_is_hg(_tdm, port))
    407             return BOOL_FALSE;
    408     }
    409 
    410     return BOOL_TRUE;
    411 }
    412 
    413 
    414 /**
    415 @name: tdm_td3_cmn_get_pipe_higig
    416 @param:
    417 
    418 Return BOOL_TRUE if the given pipe has HiGig traffic;
    419 otherwise, return BOOL_FALSE.
    420 (Chip-Specific)
    421  */
    422 int
    423 tdm_td3_cmn_get_pipe_higig(tdm_mod_t *_tdm, int cal_id)
    424 {
    425     int result = BOOL_FALSE;
    426 
    427     /* check regular ports */
    428     if (tdm_td3_cmn_get_pipe_ethernet(_tdm, cal_id) == BOOL_FALSE) {
    429         result = BOOL_TRUE;
    430     }
    431     /* check management ports */
    432     if (cal_id == TD3_IDB_PIPE_1_CAL_ID &&
    433         _tdm->_chip_data.soc_pkg.soc_vars.td3.mgmt_pm_hg == BOOL_TRUE) {
    434         result = BOOL_TRUE;
    435     }
    436 
    437     return (result);
    438 }
    439 
    440 
    441 /**
    442 @name: tdm_td3_cmn_get_pipe_cal_len_max
    443 @param:
    444 
    445 Return the size of selected calendar (regardless of frequency/higig)
    446  */
    447 int
    448 tdm_td3_cmn_get_pipe_cal_len_max(tdm_mod_t *_tdm, int cal_id)
    449 {
    450     int cal_len = 0;
    451 
    452     switch (cal_id) {
    453         case 0: cal_len = _tdm->_chip_data.cal_0.cal_len; break;
    454         case 1: cal_len = _tdm->_chip_data.cal_1.cal_len; break;
    455         case 2: cal_len = _tdm->_chip_data.cal_2.cal_len; break;
    456         case 3: cal_len = _tdm->_chip_data.cal_3.cal_len; break;
    457         case 4: cal_len = _tdm->_chip_data.cal_4.cal_len; break;
    458         case 5: cal_len = _tdm->_chip_data.cal_5.cal_len; break;
    459         case 6: cal_len = _tdm->_chip_data.cal_6.cal_len; break;
    460         case 7: cal_len = _tdm->_chip_data.cal_7.cal_len; break;
    461         default: break;
    462     }
    463 
    464     return (cal_len);
    465 }
    466 
    467 
    468 /**
    469 @name: tdm_td3_cmn_get_pipe_cal_len
    470 @param:
    471 
    472 Return valid length of selected calendar under frequency/higig constraint
    473 (Chip-Specific)
    474  */
    475 int
    476 tdm_td3_cmn_get_pipe_cal_len(tdm_mod_t *_tdm, int cal_id)
    477 {
    478     int cal_len = 0;
    479     int param_freq;
    480 
    481     param_freq = _tdm->_chip_data.soc_pkg.clk_freq;
    482 
    483     /* get calendar length */
    484     if (tdm_td3_cmn_get_pipe_higig(_tdm, cal_id) == BOOL_FALSE) {
    485         switch (param_freq) {
    486             case TD3_CLK_1700MHZ: cal_len = TD3_LEN_1700MHZ_EN; break;
    487             case TD3_CLK_1625MHZ: cal_len = TD3_LEN_1625MHZ_EN; break;
    488             case TD3_CLK_1525MHZ: cal_len = TD3_LEN_1525MHZ_EN; break;
    489             case TD3_CLK_1425MHZ: cal_len = TD3_LEN_1425MHZ_EN; break;
    490             case TD3_CLK_1325MHZ: cal_len = TD3_LEN_1325MHZ_EN; break;
    491             case TD3_CLK_1275MHZ: cal_len = TD3_LEN_1275MHZ_EN; break;
    492             case TD3_CLK_1125MHZ: cal_len = TD3_LEN_1125MHZ_EN; break;
    493             case TD3_CLK_1012MHZ: cal_len = TD3_LEN_1012MHZ_EN; break;
    494             case TD3_CLK_850MHZ:  cal_len = TD3_LEN_850MHZ_EN;  break;
    495             default:  break;
    496         }
    497     } else {
    498         switch (param_freq) {
    499             case TD3_CLK_1700MHZ: cal_len = TD3_LEN_1700MHZ_HG; break;
    500             case TD3_CLK_1625MHZ: cal_len = TD3_LEN_1625MHZ_HG; break;
    501             case TD3_CLK_1525MHZ: cal_len = TD3_LEN_1525MHZ_HG; break;
    502             case TD3_CLK_1425MHZ: cal_len = TD3_LEN_1425MHZ_HG; break;
    503             case TD3_CLK_1325MHZ: cal_len = TD3_LEN_1325MHZ_HG; break;
    504             case TD3_CLK_1275MHZ: cal_len = TD3_LEN_1275MHZ_HG; break;
    505             case TD3_CLK_1125MHZ: cal_len = TD3_LEN_1125MHZ_HG; break;
    506             case TD3_CLK_1012MHZ: cal_len = TD3_LEN_1012MHZ_HG; break;
    507             case TD3_CLK_850MHZ:  cal_len = TD3_LEN_850MHZ_HG;  break;
    508             default:  break;
    509         }
    510     }
    511     /* check validity of calendar length */
    512     if (cal_len == 0) {
    513         TDM_ERROR1("Invalid core clock frequency %0d\n", param_freq);
    514     } else if (cal_len > tdm_td3_cmn_get_pipe_cal_len_max(_tdm, cal_id)) {
    515         cal_len = 0;
    516         TDM_ERROR1("Invalid calendar length %0d (overflow)\n", cal_len);
    517     }
    518 
    519     return (cal_len);
    520 }
    521 
    522 
    523 /**
    524 @name: tdm_td3_cmn_get_pipe_cal
    525 @param:
    526 
    527 Return calendar pointer of the current pipe.
    528  */
    529 tdm_calendar_t *tdm_td3_cmn_get_pipe_cal(tdm_mod_t *_tdm)
    530 {
    531     /* return (tdm_cmn_get_pipe_cal(_tdm)); */
    532     tdm_calendar_t * cal = NULL;
    533 
    534     if (_tdm != NULL) {
    535         switch (_tdm->_core_data.vars_pkg.cal_id) {
    536             case 0:	cal=(&(_tdm->_chip_data.cal_0)); break;
    537             case 1:	cal=(&(_tdm->_chip_data.cal_1)); break;
    538             case 2:	cal=(&(_tdm->_chip_data.cal_2)); break;
    539             case 3:	cal=(&(_tdm->_chip_data.cal_3)); break;
    540             case 4:	cal=(&(_tdm->_chip_data.cal_4)); break;
    541             case 5:	cal=(&(_tdm->_chip_data.cal_5)); break;
    542             case 6:	cal=(&(_tdm->_chip_data.cal_6)); break;
    543             case 7:	cal=(&(_tdm->_chip_data.cal_7)); break;
    544             default:
    545                 TDM_PRINT1("Invalid calendar ID - %0d\n",
    546                            _tdm->_core_data.vars_pkg.cal_id);
    547                 cal = NULL;
    548                 break;
    549         }
    550     }
    551 
    552     return cal;
    553 }
    554 
    555 
    556 /**
    557 @name: tdm_td3_cmn_get_pipe_cal_prev
    558 @param:
    559 
    560 Return calendar pointer of the previous pipe.
    561  */
    562 tdm_calendar_t *tdm_td3_cmn_get_pipe_cal_prev(tdm_mod_t *_tdm)
    563 {
    564     /* return (tdm_cmn_get_pipe_cal_prev(_tdm)); */
    565     tdm_calendar_t * cal = NULL;
    566 
    567     if (_tdm != NULL) {
    568         switch (_tdm->_core_data.vars_pkg.cal_id) {
    569             case 0:	cal=(&(_tdm->_prev_chip_data.cal_0)); break;
    570             case 1:	cal=(&(_tdm->_prev_chip_data.cal_1)); break;
    571             case 2:	cal=(&(_tdm->_prev_chip_data.cal_2)); break;
    572             case 3:	cal=(&(_tdm->_prev_chip_data.cal_3)); break;
    573             case 4:	cal=(&(_tdm->_prev_chip_data.cal_4)); break;
    574             case 5:	cal=(&(_tdm->_prev_chip_data.cal_5)); break;
    575             case 6:	cal=(&(_tdm->_prev_chip_data.cal_6)); break;
    576             case 7:	cal=(&(_tdm->_prev_chip_data.cal_7)); break;
    577             default:
    578                 TDM_PRINT1("Invalid calendar ID - %0d\n",
    579                            _tdm->_core_data.vars_pkg.cal_id);
    580                 cal = NULL;
    581                 break;
    582         }
    583     }
    584 
    585     return cal;
    586 }
    587 
    588 
    589 /**
    590 @name: tdm_td3_cmn_get_same_port_dist
    591 @param:
    592  */
    593 int
    594 tdm_td3_cmn_get_same_port_dist(int slot, int dir, int *cal_main, int cal_len)
    595 {
    596     int n, k, dist = 0;
    597 
    598     if (slot < cal_len && cal_len > 0) {
    599         if (dir == TDM_DIR_UP) { /* UP direction */
    600             for (n = 1; n < cal_len; n++) {
    601                 k = (slot + cal_len - n) % cal_len;
    602                 if (cal_main[k] == cal_main[slot]) {
    603                     dist  = n;
    604                     break;
    605                 }
    606             }
    607         } else { /* DOWN direction */
    608             for (n = 1; n < cal_len; n++) {
    609                 k = (slot + n) % cal_len;
    610                 if (cal_main[k] == cal_main[slot]) {
    611                     dist  = n;
    612                     break;
    613                 }
    614             }
    615         }
    616     }
    617 
    618     return (dist);
    619 }
    620 
    621 
    622 /**
    623 @name: tdm_td3_cmn_get_speed_jitter
    624 @param:
    625  */
    626 void
    627 tdm_td3_cmn_get_speed_jitter(int port_speed, int cal_len, int *space_min, int *space_max)
    628 {
    629     int slot_req, space_frac, jitter_range, jitter_min=0, jitter_max=0;
    630 
    631     if (port_speed<SPEED_10G) {
    632         slot_req = (port_speed/100)/25;
    633     } else {
    634         slot_req = ((port_speed/10000)*100)/25;
    635     }
    636     if (slot_req>0) {
    637         space_frac  = ((cal_len*10)/slot_req)%10;
    638         jitter_range= (2*cal_len)/(slot_req*5);
    639         jitter_range= ((((2*cal_len*10)/(slot_req*5))%10)<5)?
    640                       (jitter_range):
    641                       (jitter_range+1);
    642         
    643         if (space_frac<5){
    644             jitter_min = cal_len/slot_req - jitter_range/2;
    645             jitter_max = cal_len/slot_req + jitter_range/2;
    646             jitter_max = ((jitter_range%2)==0)?
    647                         (jitter_max):
    648                         (jitter_max+1);
    649         } else {
    650             jitter_min = cal_len/slot_req - jitter_range/2;
    651             jitter_min = ((cal_len%slot_req)==0)?
    652                         (jitter_min):
    653                         (jitter_min+1);
    654             jitter_min = ((jitter_range%2)==0)?
    655                         (jitter_min):
    656                         (jitter_min-1);
    657             jitter_max = cal_len/slot_req + jitter_range/2;
    658             jitter_max = ((cal_len%slot_req)==0)?
    659                         (jitter_max):
    660                         (jitter_max+1);
    661         }
    662         jitter_min = (jitter_min<1)? (1): (jitter_min);
    663         jitter_max = (jitter_max<1)? (1): (jitter_max);
    664     }
    665     if (space_min != NULL && space_max != NULL) {
    666         *space_min = jitter_min;
    667         *space_max = jitter_max;
    668     }
    669 }