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

unimac.c (89278B)


      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  *
      7  * XGS 10/100/1000/2500 Megabit Media Access Controller Driver (unimac)
      8  *
      9  * This module is used for:
     10  *
     11  *   -  Gigabit ports on some XGS3 systems.
     12  */
     13 
     14 #include <shared/bsl.h>
     15 
     16 #include <sal/core/libc.h>
     17 
     18 #include <soc/drv.h>
     19 #include <soc/ll.h>
     20 #include <soc/error.h>
     21 #include <soc/portmode.h>
     22 #include <soc/macutil.h>
     23 #include <soc/phyctrl.h>
     24 
     25 
     26 #ifdef BCM_UNIMAC_SUPPORT
     27 
     28 #define JUMBO_MAXSZ  0x3fe8
     29 
     30 /*
     31  * Forward Declarations
     32  */
     33 mac_driver_t soc_mac_uni;
     34 
     35 #define SOC_UNIMAC_SPEED_10     0x0
     36 #define SOC_UNIMAC_SPEED_100    0x1
     37 #define SOC_UNIMAC_SPEED_1000   0x2
     38 #define SOC_UNIMAC_SPEED_2500   0x3
     39 
     40 /* EEE related defination */
     41 #define SOC_UNIMAC_MAX_EEE_SPEED    1000
     42 
     43 /* Config value of LCCDRAIN_TIMEOUT_USEC. Default is 250000 usec. */
     44 STATIC int lcc_drain_timeout[SOC_MAX_NUM_DEVICES];
     45 
     46 #ifdef BROADCOM_DEBUG
     47 static char *mac_uni_encap_mode[] = SOC_ENCAP_MODE_NAMES_INITIALIZER;
     48 static char *mac_uni_port_if_names[] = SOC_PORT_IF_NAMES_INITIALIZER;
     49 #endif /* BROADCOM_DEBUG */
     50 
     51 /*
     52  * Function:
     53  *      _mac_uni_drain_cells
     54  * Purpose:
     55  *      Wait until MMU cell count reaches zero for a specified port.
     56  * Parameters:
     57  *      unit - StrataSwitch unit #.
     58  *      port - Port number being examined.
     59  * Returns:
     60  *      SOC_E_XXX
     61  * Notes:
     62  *      Keeps polling as long as LCCCOUNT/GCCCOUNT is decrementing.
     63  *      If LCCCOUNT/GCCCOUNT stops decrementing without reaching zero,
     64  *      after a timeout period a warning message is printed
     65  *      and it gives up.
     66  *
     67  *      Before calling this routine, make sure no packets are switching
     68  *      to the port or it might never finish draining.
     69  */
     70 
     71 STATIC int
     72 _mac_uni_drain_cells(int unit, soc_port_t port)
     73 {
     74     int                 rv;
     75     uint32              flush_ctrl;
     76     int                 pause_tx, pause_rx;
     77 #ifdef BCM_GREYHOUND_SUPPORT
     78     uint32              mmu_fc = 0;
     79 #endif
     80     rv  = SOC_E_NONE;
     81 
     82     if (SOC_IS_RELOADING(unit)) {
     83         return rv;
     84     }
     85 #if defined(BCM_KATANA_SUPPORT)
     86     if (SOC_IS_KATANA(unit)) {
     87 	/* Drop out all packets in TX FIFO without egressing any packets */
     88 	SOC_IF_ERROR_RETURN
     89 	    (READ_FLUSH_CONTROLr(unit, port, &flush_ctrl));
     90 	soc_reg_field_set(unit, FLUSH_CONTROLr, &flush_ctrl, FLUSHf, 1);
     91 	SOC_IF_ERROR_RETURN
     92 	    (WRITE_FLUSH_CONTROLr(unit, port, flush_ctrl));
     93 	LOG_VERBOSE(BSL_LS_SOC_COMMON,
     94                     (BSL_META_U(unit,
     95                                 "port %d unimac TX fifo FLUSH_CONTROL.FLUSH set to 1\n"), port));
     96     }
     97 #endif /* BCM_KATANA_SUPPORT */
     98 
     99     /* First put the port in flush state - the packets from the XQ of the 
    100      * port are purged after dequeue. */
    101     SOC_IF_ERROR_RETURN
    102         (soc_mmu_flush_enable(unit, port, TRUE));
    103     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    104                 (BSL_META_U(unit,
    105                             "port %d unimac mmu flush enable completed\n"), port));
    106 #ifdef BCM_GREYHOUND_SUPPORT
    107     /* clear the MMU pause state*/
    108     if (SOC_REG_IS_VALID(unit, MMU_FC_RX_ENr)) {
    109         SOC_IF_ERROR_RETURN(
    110             READ_MMU_FC_RX_ENr(unit, port, &mmu_fc));
    111         SOC_IF_ERROR_RETURN(
    112             WRITE_MMU_FC_RX_ENr(unit,port,0));
    113     }
    114 #endif
    115     /* Disable pause function */
    116     SOC_IF_ERROR_RETURN
    117         (soc_mac_uni.md_pause_get(unit, port, &pause_tx, &pause_rx));
    118     SOC_IF_ERROR_RETURN
    119         (soc_mac_uni.md_pause_set(unit, port, 0, 0));
    120 
    121     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    122                 (BSL_META_U(unit,
    123                             "port %d unimac saved pause and pfc state\n"), port));
    124 
    125     if (!SOC_IS_KATANA(unit)) {
    126 	/* Drop out all packets in TX FIFO without egressing any packets */
    127 	SOC_IF_ERROR_RETURN
    128 	    (READ_FLUSH_CONTROLr(unit, port, &flush_ctrl));
    129 	soc_reg_field_set(unit, FLUSH_CONTROLr, &flush_ctrl, FLUSHf, 1);
    130 	SOC_IF_ERROR_RETURN
    131 	    (WRITE_FLUSH_CONTROLr(unit, port, flush_ctrl));
    132 	LOG_VERBOSE(BSL_LS_SOC_COMMON,
    133                     (BSL_META_U(unit,
    134                                 "port %d unimac TX fifo FLUSH_CONTROL.FLUSH set to 1\n"), port));
    135     }
    136     /* Notify PHY driver */
    137     SOC_IF_ERROR_RETURN
    138         (soc_phyctrl_notify(unit, port, 
    139                             phyEventStop, PHY_STOP_DRAIN));
    140 
    141     /* Disable switch egress metering so that packet draining is not rate
    142      * limited.
    143      */
    144     rv = soc_egress_drain_cells(unit, port, lcc_drain_timeout[unit]);
    145     if (SOC_E_NONE == rv) {
    146         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    147                     (BSL_META_U(unit,
    148                            "port %d unimac egress packet draining completed\n"),
    149                            port));
    150     }
    151 
    152     /* Notify PHY driver */
    153     SOC_IF_ERROR_RETURN
    154         (soc_phyctrl_notify(unit, port, 
    155                             phyEventResume, PHY_STOP_DRAIN));
    156 
    157     /* Soft-reset is recommended here. 
    158      * SOC_IF_ERROR_RETURN
    159      *     (soc_mac_uni.md_control_set(unit, port, SOC_MAC_CONTROL_SW_RESET,
    160      *                                 TRUE));
    161      * SOC_IF_ERROR_RETURN
    162      *     (soc_mac_uni.md_control_set(unit, port, SOC_MAC_CONTROL_SW_RESET,
    163      *                                 FALSE));
    164      */
    165   
    166     /* Bring the TxFifo out of flush */
    167     soc_reg_field_set(unit, FLUSH_CONTROLr, &flush_ctrl, FLUSHf, 0);
    168     SOC_IF_ERROR_RETURN
    169         (WRITE_FLUSH_CONTROLr(unit, port, flush_ctrl));
    170     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    171                 (BSL_META_U(unit,
    172                             "port %d unimac TX fifo FLUSH_CONTROL.FLUSH set to 0\n"), port));
    173 
    174 
    175 #ifdef BCM_GREYHOUND_SUPPORT
    176     /* restore the MMU pause state*/
    177     if (SOC_REG_IS_VALID(unit, MMU_FC_RX_ENr)) {
    178         SOC_IF_ERROR_RETURN(
    179             WRITE_MMU_FC_RX_ENr(unit, port, mmu_fc));
    180     }
    181 #endif
    182 
    183     /* Restore original pause configuration */
    184     SOC_IF_ERROR_RETURN
    185         (soc_mac_uni.md_pause_set(unit, port, pause_tx, pause_rx));
    186 
    187 #if defined(BCM_KATANA_SUPPORT)
    188     if (SOC_IS_KATANA(unit)) {
    189          LOG_VERBOSE(BSL_LS_SOC_COMMON,
    190                      (BSL_META_U(unit,
    191                                  "KATANA port %d mmu flush disable will be invoked during port re-enable"),
    192                       port));
    193     } else
    194 #endif
    195     {
    196         /* Bring the switch MMU out of flush */
    197         SOC_IF_ERROR_RETURN
    198            (soc_mmu_flush_enable(unit, port, FALSE));
    199         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    200                     (BSL_META_U(unit,
    201                                 "port %d unimac mmu flush disabled\n"), port));
    202     }
    203     return rv;
    204 }
    205 
    206 /*
    207  * Function:
    208  *      mac_uni_init
    209  * Purpose:
    210  *      Initialize UniMAC into a known good state.
    211  * Parameters:
    212  *      unit - StrataSwitch unit #.
    213  *      port - StrataSwitch port # on unit.
    214  * Returns:
    215  *      SOC_E_XXX
    216  * Notes:
    217  *      The initialization speed/duplex is arbitrary and must be
    218  *      updated by linkscan before enabling the MAC.
    219  */
    220 
    221 STATIC  int
    222 mac_uni_init(int unit, soc_port_t port)
    223 {
    224     uint32              command_config, ocommand_config, speed, rval32;
    225     int                 frame_max;
    226     int                 ignore_pause;
    227 
    228     LOG_VERBOSE(BSL_LS_SOC_GE,
    229                 (BSL_META_U(unit,
    230                             "mac_uni_init: unit %d port %s\n"),
    231                  unit, SOC_PORT_NAME(unit, port)));
    232 
    233     /* Get MAC configurations from config settings. */
    234     lcc_drain_timeout[unit] = soc_property_get(unit, spn_LCCDRAIN_TIMEOUT_USEC, 
    235                                          250000);
    236     SOC_IF_ERROR_RETURN
    237         (soc_port_blk_init(unit, port));
    238 
    239     frame_max = IS_ST_PORT(unit, port) ? JUMBO_MAXSZ : 1518;
    240 
    241     soc_mac_uni.md_frame_max_set(unit, port, frame_max);
    242 
    243     /* First put the MAC in reset and sleep */
    244     SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
    245                                                    SOC_MAC_CONTROL_SW_RESET,
    246                                                    TRUE));
    247 
    248     /* Do the initialization */
    249     SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config));
    250     ocommand_config = command_config;
    251 
    252     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ENAf, 0);
    253     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 0);
    254     speed = IS_FE_PORT(unit, port) ? SOC_UNIMAC_SPEED_100 : SOC_UNIMAC_SPEED_1000;
    255     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, ETH_SPEEDf, 
    256                       speed);
    257     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PROMIS_ENf, 1);
    258     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAD_ENf, 0);
    259     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CRC_FWDf, 1);
    260 #ifdef BCM_SHADOW_SUPPORT
    261     if (SOC_IS_SHADOW(unit)) {
    262         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAD_ENf, 1);
    263         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CRC_FWDf, 0);
    264         /* Quickfix - Enable external config for SGMII mode in shadow */
    265         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config,
    266                           ENA_EXT_CONFIGf, 1);
    267     }
    268 #endif
    269     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAUSE_FWDf, 0);
    270 
    271     /* Ignore pause if using as stack port */
    272     ignore_pause = IS_ST_PORT(unit, port) ? 1 : 0;
    273     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAUSE_IGNOREf,
    274                       ignore_pause);
    275     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, IGNORE_TX_PAUSEf,
    276                       ignore_pause);
    277 
    278     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ADDR_INSf, 0);
    279     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, HD_ENAf, 0);
    280     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, LOOP_ENAf, 0);
    281     
    282     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CNTL_FRM_ENAf, 0);
    283     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, NO_LGTH_CHECKf,
    284                       1);
    285     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, LINE_LOOPBACKf,
    286                       0);
    287     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ERR_DISCf, 0);
    288     if (soc_reg_field_valid(unit, COMMAND_CONFIGr, PRBL_ENAf)) {
    289         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PRBL_ENAf, 0);
    290     }
    291     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CNTL_FRM_ENAf, 1);
    292 
    293     /* For Hawkeye, let the bit ENA_EXT_CONFIG to stay the default value 
    294      * without changing by S/W.
    295      * It is same as unmanaged mode and suggested by design team during 
    296      * bringup.
    297      */
    298     if(!SOC_IS_HAWKEYE(unit)) {
    299         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, 
    300                           ENA_EXT_CONFIGf,
    301                           PHY_SGMII_AUTONEG_MODE(unit, port) ? 1 : 0);
    302     }
    303 
    304     if (PHY_SGMII_AUTONEG_MODE(unit, port) &&
    305             soc_reg_field_valid(unit,COMMAND_CONFIGr,SW_OVERRIDE_RXf) &&
    306             soc_reg_field_valid(unit,COMMAND_CONFIGr,SW_OVERRIDE_TXf)) {
    307         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config,
    308                            SW_OVERRIDE_RXf, 1);
    309         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config,
    310                            SW_OVERRIDE_TXf, 1);
    311     }
    312 
    313     if (ocommand_config != command_config) {
    314 	SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config));
    315     }
    316 
    317     /* Initialize mask for purging packet data received from the MAC */
    318     SOC_IF_ERROR_RETURN(soc_packet_purge_control_init(unit, port));
    319 
    320     /* Bring the UniMAC out of reset */
    321     SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
    322                                                    SOC_MAC_CONTROL_SW_RESET,
    323                                                    FALSE));
    324 
    325     /* Pulse the Serdes AN if using auto_cfg mode */
    326     if (PHY_SGMII_AUTONEG_MODE(unit, port)) {
    327         SOC_IF_ERROR_RETURN
    328             (soc_phyctrl_notify(unit, port, phyEventAutoneg, 0));
    329         SOC_IF_ERROR_RETURN
    330             (soc_phyctrl_notify(unit, port, phyEventAutoneg, 1));        
    331     }
    332 
    333     rval32 = 0;
    334     soc_reg_field_set(unit, PAUSE_CONTROLr, &rval32, ENABLEf, 1);
    335 
    336     if (soc_feature(unit, soc_feature_pause_control_update)) {
    337         soc_reg_field_set(unit, PAUSE_CONTROLr, &rval32, VALUEf, 0xc000);
    338     } else {
    339         soc_reg_field_set(unit, PAUSE_CONTROLr, &rval32, VALUEf, 0x1ffff);
    340     }
    341 
    342     SOC_IF_ERROR_RETURN(WRITE_PAUSE_CONTROLr(unit, port, rval32));
    343 
    344     SOC_IF_ERROR_RETURN(WRITE_PAUSE_QUANTr(unit, port, 0xffff));
    345 
    346     if (SOC_REG_IS_VALID(unit, MAC_PFC_REFRESH_CTRLr)) {
    347         soc_field_t fields[] = { PFC_REFRESH_ENf, PFC_REFRESH_TIMERf };
    348         uint32 values[] = { 1, 0xc000 };
    349         SOC_IF_ERROR_RETURN
    350             (soc_reg_fields32_modify(unit, MAC_PFC_REFRESH_CTRLr, port, 2,
    351                                      fields, values));
    352     }
    353 
    354     SOC_IF_ERROR_RETURN(WRITE_TX_IPG_LENGTHr(unit, port, 12));
    355 
    356     /* Set egress enable */
    357     SOC_IF_ERROR_RETURN
    358         (soc_egress_enable(unit, port, TRUE));
    359 
    360     /* assigning proper setting for EEE feature :
    361      * Note :
    362      *  - GE speed force assigned for timer setting 
    363      */
    364     if (soc_feature(unit, soc_feature_eee)) {
    365         SOC_IF_ERROR_RETURN(soc_port_eee_timers_init(unit, 
    366                 port, SOC_UNIMAC_MAX_EEE_SPEED));
    367     }
    368 
    369     return SOC_E_NONE;
    370 }
    371 
    372 /*
    373  * Function:
    374  *      mac_uni_enable_set
    375  * Purpose:
    376  *      Enable or disable MAC
    377  * Parameters:
    378  *      unit - StrataSwitch unit #.
    379  *      port - Port number on unit.
    380  *      enable - TRUE to enable, FALSE to disable
    381  * Returns:
    382  *      SOC_E_XXX
    383  */
    384 
    385 STATIC int
    386 mac_uni_enable_set(int unit, soc_port_t port, int enable)
    387 {
    388     uint32              command_config, tx_ena, rx_ena;
    389     pbmp_t              mask;
    390     uint32 version, merge_config;
    391     int unimac_version;
    392 
    393     LOG_VERBOSE(BSL_LS_SOC_GE,
    394                 (BSL_META_U(unit,
    395                             "mac_uni_enable_set: unit %d port %s enable=%s\n"),
    396                  unit, SOC_PORT_NAME(unit, port),
    397                  enable ? "True" : "False"));
    398 
    399     SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config));
    400     tx_ena = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, TX_ENAf);
    401     rx_ena = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, RX_ENAf);
    402 
    403     /* We have seen instances when there are a flurry of disable/enable calls 
    404        where the TX_ENA and RX_ENA are set, but the mask2 bit is clear for the port. 
    405        This resulted in the MAC not actually being enabled for the port. The logic 
    406        below ensures that we consider the membership of the mask2 bitmap before 
    407        returning early. */ 
    408     soc_link_mask2_get(unit, &mask); 
    409     if ((tx_ena == rx_ena) && 
    410         (tx_ena == (enable ? 1 : 0)) && 
    411         (enable ? SOC_PBMP_MEMBER(mask, port) : !SOC_PBMP_MEMBER(mask, port))) { 
    412         return SOC_E_NONE; 
    413     } 
    414 
    415     /* First put the MAC in reset */
    416     SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
    417                                                    SOC_MAC_CONTROL_SW_RESET,
    418                                                    TRUE));
    419 
    420     /* de-assert RX_ENA and TX_ENA */
    421     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 1);
    422     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ENAf, 0);
    423     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 0);
    424     SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config));
    425     sal_udelay(2);
    426 
    427     /* Bring the MAC out of reset */
    428     SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
    429                                                    SOC_MAC_CONTROL_SW_RESET,
    430                                                    FALSE));
    431 
    432     if (!enable) {
    433         if (soc_feature(unit, soc_feature_unimac_reset_wo_clock)) {
    434             SOC_IF_ERROR_RETURN
    435                 (soc_pgw_rx_fifo_reset(unit, port, TRUE));
    436         }
    437 
    438         soc_link_mask2_get(unit, &mask);
    439         SOC_PBMP_PORT_REMOVE(mask, port);
    440         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    441         /*
    442          * Disable MMU port
    443          * for some devices where EPC_LINK can not block the SOBMH from cpu and
    444          * no mechanism is avalible to reset EDATABUF.
    445          */
    446         SOC_IF_ERROR_RETURN(soc_port_mmu_buffer_enable(unit, port, FALSE));
    447 
    448         SOC_IF_ERROR_RETURN(_mac_uni_drain_cells(unit, port));
    449         SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
    450 						       SOC_MAC_CONTROL_SW_RESET,
    451 						       TRUE));
    452         SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, phyEventStop,
    453                                                PHY_STOP_MAC_DIS));
    454         /* Drop incoming packets from this port in the ingress pipeline */
    455         if (SOC_REG_IS_VALID(unit, PKT_DROP_ENABLEr) && 
    456             !(SOC_IS_SC_CQ(unit) && 
    457               (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_QGPORT)) &&
    458             !(SOC_IS_ENDURO(unit) && 
    459               (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_GPORT)) &&
    460             !(SOC_IS_HURRICANE(unit) && 
    461               (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_GPORT))) {
    462             SOC_IF_ERROR_RETURN(WRITE_PKT_DROP_ENABLEr(unit, port, 1));
    463         }
    464 
    465         /* Forces rx_lost_eop sequence */
    466         if (SOC_REG_IS_VALID(unit, UMAC_REV_IDr) &&
    467             SOC_REG_IS_VALID(unit, MAC_MERGE_CONFIGr)) {
    468 
    469             SOC_IF_ERROR_RETURN(READ_UMAC_REV_IDr(unit, port, &version));
    470             unimac_version =
    471                 soc_reg_field_get(
    472                     unit, UMAC_REV_IDr, version, REVISION_ID_MAJORf);
    473             if (unimac_version == 4) {
    474                 /* Set SW force */
    475                 SOC_IF_ERROR_RETURN(
    476                     READ_MAC_MERGE_CONFIGr(unit, port, &merge_config));
    477                 soc_reg_field_set(
    478                     unit, MAC_MERGE_CONFIGr, &merge_config,
    479                     SW_FORCE_RX_LOST_EOPf, 1);
    480                 SOC_IF_ERROR_RETURN(
    481                     WRITE_MAC_MERGE_CONFIGr(unit, port, merge_config));
    482 
    483                 /* Clear SW force */
    484                 SOC_IF_ERROR_RETURN(
    485                     READ_MAC_MERGE_CONFIGr(unit, port, &merge_config));
    486                 soc_reg_field_set(
    487                     unit, MAC_MERGE_CONFIGr, &merge_config,
    488                     SW_FORCE_RX_LOST_EOPf, 0);
    489                 SOC_IF_ERROR_RETURN(
    490                     WRITE_MAC_MERGE_CONFIGr(unit, port, merge_config));
    491             }
    492         }
    493     } else {
    494         /* Stop the ingress pipeline from dropping packets from this port */
    495 #if defined(BCM_KATANA_SUPPORT)
    496         if (SOC_IS_KATANA(unit)) {
    497             SOC_IF_ERROR_RETURN
    498               (soc_mmu_flush_enable(unit, port, FALSE));
    499         }
    500 #endif
    501         if (SOC_REG_IS_VALID(unit, PKT_DROP_ENABLEr) && 
    502             !(SOC_IS_SC_CQ(unit) && 
    503               (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_QGPORT)) &&
    504             !(SOC_IS_ENDURO(unit) && 
    505               (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_GPORT)) &&
    506             !(SOC_IS_HURRICANE(unit) && 
    507               (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_GPORT))) {
    508             SOC_IF_ERROR_RETURN(WRITE_PKT_DROP_ENABLEr(unit, port, 0));
    509         }
    510 #if defined(BCM_SCORPION_SUPPORT)
    511         if (soc_feature(unit, soc_feature_priority_flow_control)) {
    512             /* Flush MMU XOFF state with toggle bit */
    513             if (SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
    514                 SOC_IF_ERROR_RETURN
    515                       (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port,
    516                                           FORCE_PFC_XONf, 1));
    517                 SOC_IF_ERROR_RETURN
    518                       (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port,
    519                                           FORCE_PFC_XONf, 0));
    520             }
    521         }
    522 #endif /* BCM_SCORPION_SUPPORT */
    523         /* if it is to enable, assert RX_ENA and TX_ENA */
    524         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf,
    525                           0);
    526         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ENAf, 1);
    527         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 1);
    528         SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config));
    529         sal_udelay(2);
    530 
    531         /* Enable MMU port */
    532         SOC_IF_ERROR_RETURN(soc_port_mmu_buffer_enable(unit, port, TRUE));
    533 
    534         soc_link_mask2_get(unit, &mask);
    535         SOC_PBMP_PORT_ADD(mask, port);
    536         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    537         SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
    538 						       SOC_MAC_CONTROL_SW_RESET,
    539 						       TRUE));
    540         SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, phyEventResume,
    541                                                PHY_STOP_MAC_DIS));
    542         SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
    543 						       SOC_MAC_CONTROL_SW_RESET,
    544 						       FALSE));
    545 
    546         if (soc_feature(unit, soc_feature_unimac_reset_wo_clock)) {
    547             SOC_IF_ERROR_RETURN
    548                 (soc_pgw_rx_fifo_reset(unit, port, FALSE));
    549         }
    550     }
    551 
    552     return SOC_E_NONE;
    553 }
    554 
    555 /*
    556  * Function:
    557  *      mac_uni_enable_get
    558  * Purpose:
    559  *      Get UniMAC enable state
    560  * Parameters:
    561  *      unit - StrataSwitch unit #.
    562  *      port - Port number on unit.
    563  *      enable - (OUT) TRUE if enabled, FALSE if disabled
    564  * Returns:
    565  *      SOC_E_XXX
    566  */
    567 
    568 STATIC int
    569 mac_uni_enable_get(int unit, soc_port_t port, int *enable)
    570 {
    571     uint32		command_config;
    572 
    573     SOC_IF_ERROR_RETURN
    574         (READ_COMMAND_CONFIGr(unit, port, &command_config));
    575 
    576     *enable = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config,
    577                                 RX_ENAf);
    578 
    579     LOG_VERBOSE(BSL_LS_SOC_GE,
    580                 (BSL_META_U(unit,
    581                             "mac_uni_enable_get: unit %d port %s enable=%s\n"),
    582                  unit, SOC_PORT_NAME(unit, port),
    583                  *enable ? "True" : "False"));
    584     return SOC_E_NONE;
    585 }
    586 
    587 
    588 #if defined(BCM_KATANA_SUPPORT)
    589 /*
    590  * Function:
    591  *      _mac_uni_timestamp_delay_set
    592  * Purpose:
    593  *      Set Timestamp delay for one-step to account for lane and pipeline delay.
    594  * Parameters:
    595  *      unit - Switch unit #.
    596  *      port - Port number on unit.
    597  * Returns:
    598  *      SOC_E_XXX
    599  */
    600 STATIC int
    601 _mac_uni_timestamp_delay_set(int unit, soc_port_t port, int speed)
    602 {
    603     uint32 ctrl;
    604     int ts_adjust;
    605     uint32 field;
    606     LOG_VERBOSE(BSL_LS_SOC_GE,
    607                 (BSL_META_U(unit,
    608                             "mac_uni_timestamp_delay_set: unit %d port %s speed %d\n"),
    609                  unit, SOC_PORT_NAME(unit, port), speed));
    610     /* 
    611      * KT-1379 : UniMAC Rx pipeline delay accounting on Tx path 
    612      * can cause issue for asymmetric paths/ speeds
    613      * UMAC_TIMESTAMP_ADJUST.AUTO_ADJUST programmed to 0. 
    614      * Per-ingress port EGR_1588_LINK_DELAY.LINK_DELAY registers.
    615      *      - MACRxPipelineDelay(1000M ingress speed) = 232ns
    616      *      - MACRxPipelineDelay(100M ingress speed) = 2320ns
    617      *      - MACRxPipelineDelay(10M ingress speed) = 23200ns
    618      */
    619 
    620     if (SOC_REG_IS_VALID(unit, UMAC_TIMESTAMP_ADJUSTr)) {
    621         ts_adjust = soc_property_port_get(unit, port, spn_TIMESTAMP_ADJUST(speed), 0);
    622 
    623         if (SOC_E_NONE != soc_reg_signed_field_mask(unit, UMAC_TIMESTAMP_ADJUSTr,
    624                                                     ADJUSTf, ts_adjust, &field)) {
    625             LOG_WARN(BSL_LS_SOC_PORT, (BSL_META_U(unit,
    626                                                   "%s property out of bounds (is %d)\n"),
    627                                        spn_TIMESTAMP_ADJUST(speed), ts_adjust));
    628             field = 0;
    629         }
    630         SOC_IF_ERROR_RETURN(READ_UMAC_TIMESTAMP_ADJUSTr(unit, port, &ctrl));
    631         soc_reg_field_set(unit, UMAC_TIMESTAMP_ADJUSTr, &ctrl, 
    632                           AUTO_ADJUSTf, 0 );
    633         soc_reg_field_set(unit, UMAC_TIMESTAMP_ADJUSTr, &ctrl, 
    634                           ADJUSTf, ts_adjust);
    635         SOC_IF_ERROR_RETURN(WRITE_UMAC_TIMESTAMP_ADJUSTr(unit, port, ctrl));
    636     }
    637 
    638     return SOC_E_NONE;
    639 }
    640 #endif /* defined(BCM_KATANA_SUPPORT) */
    641 
    642 /*
    643  * Function:
    644  *      mac_uni_ifg_to_ipg
    645  * Description:
    646  *      Converts the inter-frame gap specified in bit-times into a value
    647  *      suitable to be programmed into the IPG register
    648  * Parameters:
    649  *      unit   - Device number
    650  *      port   - Port number
    651  *      speed  - the speed for which the IFG is being set
    652  *      duplex - the duplex for which the IFG is being set
    653  *      ifg    - Inter-frame gap in bit-times
    654  *      ipg    - (OUT) the value to be written into IPG
    655  * Return Value:
    656  *      BCM_E_XXX
    657  * Notes:
    658  *      The function makes sure the calculated IPG value will not cause
    659  *      hardware to fail. If the requested ifg value cannot be supported in
    660  *      hardware, the function will choose a value that approximates the
    661  *      requested value as best as possible.
    662  *
    663  *      Specifically:
    664  *         -- Current chips only support ifg which is divisible by 8. If
    665  *            the specified ifg is not divisible by 8, it will be rounded
    666  *            to the next multiplier of 8 (65 will result in 72).
    667  *         -- ifg < 64 are not supported
    668  *
    669  *      This function supports only GE portion of GE MAC (FE portion is
    670  *      supported by mac_fe_ipg_* functions
    671  */
    672 STATIC int
    673 mac_uni_ifg_to_ipg(int unit, soc_port_t port, int speed, int duplex,
    674                   int ifg, int *ipg)
    675 {
    676     int         real_ifg;
    677 
    678     /* 
    679      * Silently adjust the specified ifp bits to valid value
    680      *  - valid value: 8 to 64 bytes (i.e. multiple of 8 bits)
    681      */
    682     real_ifg = ifg < 64 ? 64 : (ifg > 512 ? 512 : (ifg + 7) & (0x7f << 3));
    683     *ipg = real_ifg / 8;
    684 
    685     return SOC_E_NONE;
    686 }
    687 
    688 /*
    689  * Function:
    690  *      mac_uni_ipg_to_ifg
    691  * Description:
    692  *      Converts the IPG register value into the inter-frame gap expressed in
    693  *      bit-times
    694  * Parameters:
    695  *      unit   - Device number
    696  *      port   - Port number
    697  *      speed  - the speed for which the IFG is being set
    698  *      duplex - the duplex for which the IFG is being set
    699  *      ipg    - the value in the IPG register
    700  *      ifg    - Inter-frame gap in bit-times
    701  * Return Value:
    702  *      BCM_E_XXX
    703  * Notes:
    704  *      This function supports only GE portion of GE MAC (FE portion is
    705  *      supported by mac_fe_ipg_* functions
    706  */
    707 STATIC int
    708 mac_uni_ipg_to_ifg(int unit, soc_port_t port, int speed, int duplex,
    709                   int ipg, int *ifg)
    710 {
    711     /*
    712      * Now we need to convert the value according to various chips'
    713      * peculiarities (there are none as of now)
    714      */
    715     *ifg = ipg * 8;
    716 
    717     return SOC_E_NONE;
    718 }
    719 
    720 /*
    721  * Function:
    722  *      mac_uni_ipg_update
    723  * Purpose:
    724  *      Set the IPG appropriate for current duplex
    725  * Parameters:
    726  *      unit - StrataSwitch unit #.
    727  *      port - Port number on unit.
    728  * Notes:
    729  *      The current duplex is read from the hardware registers.
    730  */
    731 
    732 STATIC int
    733 mac_uni_ipg_update(int unit, int port)
    734 {
    735     int                 fd, speed, ipg, ifg;
    736     uint32              rval;
    737     soc_ipg_t           *si = &SOC_PERSIST(unit)->ipg[port];
    738 
    739     SOC_IF_ERROR_RETURN(soc_mac_uni.md_duplex_get(unit, port, &fd));
    740     SOC_IF_ERROR_RETURN(soc_mac_uni.md_speed_get(unit, port, &speed));
    741 
    742     if (fd) {
    743         switch (speed) {
    744 	case 10:
    745             ifg = si->fd_10;
    746             break;
    747         case 100:
    748             ifg = si->fd_100;
    749             break;
    750         case 1000:
    751             ifg = si->fd_1000;
    752             break;
    753         case 2500:
    754             ifg = si->fd_2500;
    755             break;
    756         default:
    757             return SOC_E_INTERNAL;
    758             break;
    759         }
    760     } else {
    761         switch (speed) {
    762         case 10:
    763             ifg = si->hd_10;
    764             break;
    765         case 100:
    766             ifg = si->hd_100;
    767             break;
    768         default:
    769             return SOC_E_INTERNAL;
    770             break;
    771         }
    772     }
    773 
    774     /*
    775      * Convert the ifg value from bit-times into IPG register-specific value
    776      */
    777     SOC_IF_ERROR_RETURN(mac_uni_ifg_to_ipg(unit, port, speed, fd, ifg, &ipg));
    778 
    779     /*
    780      * Program the appropriate register
    781      */
    782     SOC_IF_ERROR_RETURN
    783         (WRITE_TX_IPG_LENGTHr(unit, port, ipg));
    784 
    785     /* Do not process any packets that have less than 8 bytes IPG */
    786     SOC_IF_ERROR_RETURN(READ_IPG_HD_BKP_CNTLr(unit, port, &rval));
    787     soc_reg_field_set(unit, IPG_HD_BKP_CNTLr, &rval, IPG_CONFIG_RXf,
    788                       speed > 1000 ? 5 : speed == 1000 ? 6 : 12);
    789     SOC_IF_ERROR_RETURN(WRITE_IPG_HD_BKP_CNTLr(unit, port, rval));
    790 
    791     return SOC_E_NONE;
    792 }
    793 
    794 /*
    795  * Function:
    796  *      mac_uni_duplex_set
    797  * Purpose:
    798  *      Set UniMAC in the specified duplex mode.
    799  * Parameters:
    800  *      unit - StrataSwitch unit #.
    801  *      port - StrataSwitch port # on unit.
    802  *      duplex - Boolean: true --> full duplex, false --> half duplex.
    803  * Returns:
    804  *      SOC_E_XXX
    805  * Notes:
    806  *      Programs an IFG time appropriate to speed and duplex.
    807  */
    808 
    809 STATIC int
    810 mac_uni_duplex_set(int unit, soc_port_t port, int duplex)
    811 {
    812     uint32 	command_config, ocommand_config;
    813     int         speed;   
    814 
    815     LOG_VERBOSE(BSL_LS_SOC_GE,
    816                 (BSL_META_U(unit,
    817                             "mac_uni_duplex_set: unit %d port %s duplex=%s\n"),
    818                  unit, SOC_PORT_NAME(unit, port),
    819                  duplex ? "Full" : "Half"));
    820 
    821     if (PHY_SGMII_AUTONEG_MODE(unit, port)) {
    822         return SOC_E_NONE;
    823     }
    824     
    825     SOC_IF_ERROR_RETURN(soc_mac_uni.md_speed_get(unit, port, &speed));
    826 
    827     if (speed >= 1000) {
    828         /*
    829          * program the bit full-duplex for speed 1000 or 2500Mbps.
    830          */
    831         duplex = 1;
    832     }
    833 
    834     SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config));
    835     ocommand_config = command_config;
    836 
    837     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, HD_ENAf, 
    838                       duplex ? 0 : 1);
    839     if (command_config == ocommand_config) {
    840         return SOC_E_NONE;
    841     }
    842 
    843     /* First put the MAC in reset */ 
    844     SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
    845                                                    SOC_MAC_CONTROL_SW_RESET,
    846                                                    TRUE));
    847 
    848     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 1);
    849     SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config));
    850  
    851     /* Set IPG to match new duplex */
    852     SOC_IF_ERROR_RETURN(mac_uni_ipg_update(unit, port));
    853 
    854     /*
    855      * Notify internal PHY driver of duplex change in case it is being
    856      * used as pass-through to an external PHY.
    857      */
    858     SOC_IF_ERROR_RETURN
    859         (soc_phyctrl_notify(unit, port, phyEventDuplex, duplex));
    860 
    861     /* Bring the MAC out of reset */
    862     SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
    863                                                    SOC_MAC_CONTROL_SW_RESET,
    864                                                    FALSE));
    865 
    866     return SOC_E_NONE;
    867 }
    868 
    869 /*
    870  * Function:
    871  *      mac_uni_duplex_get
    872  * Purpose:
    873  *      Get UniMAC duplex mode.
    874  * Parameters:
    875  *      unit - StrataSwitch unit #.
    876  *      port - StrataSwitch port # on unit.
    877  *      duplex - (OUT) Boolean: true --> full duplex, false --> half duplex.
    878  * Returns:
    879  *      SOC_E_XXX
    880  */
    881 
    882 STATIC int
    883 mac_uni_duplex_get(int unit, soc_port_t port, int *duplex)
    884 {
    885     uint32 command_config;
    886     int    speed;
    887 
    888     SOC_IF_ERROR_RETURN(soc_mac_uni.md_speed_get(unit, port, &speed));
    889 
    890     if ((1000 == speed) || (2500 == speed)) {
    891         *duplex = TRUE;
    892     } else {
    893         SOC_IF_ERROR_RETURN
    894             (READ_COMMAND_CONFIGr(unit, port, &command_config));
    895 
    896         *duplex = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 
    897                                     HD_ENAf) ? FALSE : TRUE;
    898     }
    899 
    900     LOG_VERBOSE(BSL_LS_SOC_GE,
    901                 (BSL_META_U(unit,
    902                             "mac_uni_duplex_get: unit %d port %s duplex=%s\n"),
    903                  unit, SOC_PORT_NAME(unit, port),
    904                  *duplex ? "Full" : "Half"));
    905     return SOC_E_NONE;
    906 }
    907 
    908 /*
    909  * Function:
    910  *      mac_uni_speed_set
    911  * Purpose:
    912  *      Set UniMAC in the specified speed.
    913  * Parameters:
    914  *      unit - StrataSwitch unit #.
    915  *      port - Port number on unit.
    916  *      speed - 10,100,1000, 2500 for speed.
    917  * Returns:
    918  *      SOC_E_XXX
    919  * Notes:
    920  *      Programs an IFG time appropriate to speed and duplex.
    921  */
    922 
    923 STATIC int
    924 mac_uni_speed_set(int unit, soc_port_t port, int speed)
    925 {
    926     uint32  command_config;
    927     int     speed_select;
    928     uint32  cur_speed;
    929 
    930     LOG_VERBOSE(BSL_LS_SOC_GE,
    931                 (BSL_META_U(unit,
    932                             "mac_uni_speed_set: unit %d port %s speed=%dMb\n"),
    933                  unit, SOC_PORT_NAME(unit, port),
    934                  speed));
    935 
    936     if (PHY_SGMII_AUTONEG_MODE(unit, port)) {
    937         return SOC_E_NONE;
    938     }
    939 
    940     SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config));
    941     cur_speed = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 
    942                                   ETH_SPEEDf);
    943 
    944     switch (speed) {
    945     case 10:
    946         speed_select = SOC_UNIMAC_SPEED_10;
    947 	break;
    948     /* support non-standard speed in Broadreach mode */
    949     case 20:
    950     case 25:
    951     case 33:
    952     case 50:
    953 	/* fall through to case 100 */
    954     case 100:
    955         speed_select = SOC_UNIMAC_SPEED_100;
    956 	break;
    957     case 1000:
    958         speed_select = SOC_UNIMAC_SPEED_1000;
    959         break;
    960     case 2500:
    961         speed_select = SOC_UNIMAC_SPEED_2500;
    962         break;
    963     case 0:
    964         return (SOC_E_NONE);              /* Support NULL PHY */            
    965     default:
    966         return (SOC_E_CONFIG);
    967     }
    968 
    969     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, 
    970                       ETH_SPEEDf, speed_select);
    971 
    972     /* First reset the MAC */
    973     SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
    974                                                    SOC_MAC_CONTROL_SW_RESET,
    975                                                    TRUE));
    976 
    977     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 1);
    978     SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config));
    979 
    980     /*
    981      * Notify internal PHY driver of speed change in case it is being
    982      * used as pass-through to an external PHY.
    983      */
    984 	if (! PHY_REPEATER(unit, port)) {
    985 		SOC_IF_ERROR_RETURN
    986 			(soc_phyctrl_notify(unit, port, phyEventSpeed, speed));
    987 	}
    988 
    989      /* Set IPG to match new speed */
    990     SOC_IF_ERROR_RETURN(mac_uni_ipg_update(unit, port));
    991 
    992 
    993     /* Bring the MAC out of reset */
    994     SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
    995                                                    SOC_MAC_CONTROL_SW_RESET,
    996                                                    FALSE));
    997 
    998     /* MAC speed switch results in a tx clock glitch to the serdes in 100fx mode.
    999      * reset serdes txfifo clears this condition. However this reset triggers
   1000      * a link transition. Do not apply this reset if speed is already in 100M
   1001      */
   1002     if ((speed == 100) && (cur_speed != SOC_UNIMAC_SPEED_100)) {
   1003         (void)soc_phyctrl_notify(unit, port, phyEventTxFifoReset, 100);
   1004     }
   1005 
   1006 #if defined(BCM_KATANA_SUPPORT)
   1007     /* Set unimac timestamp delay */
   1008     if (SOC_IS_KATANAX(unit)) {
   1009         SOC_IF_ERROR_RETURN(_mac_uni_timestamp_delay_set(unit,port,speed));
   1010     }
   1011 #endif
   1012     return (SOC_E_NONE);
   1013 }
   1014 
   1015 /*
   1016  * Function:
   1017  *      mac_uni_speed_get
   1018  * Purpose:
   1019  *      Get GE MAC speed
   1020  * Parameters:
   1021  *      unit - StrataSwitch unit #.
   1022  *      port - Port number on unit.
   1023  *      speed - (OUT) speed in Mb (10/100/1000)
   1024  * Returns:
   1025  *      SOC_E_NONE
   1026  */
   1027 
   1028 STATIC int
   1029 mac_uni_speed_get(int unit, soc_port_t port, int *speed)
   1030 {
   1031     uint32 		command_config, uni_speed;
   1032     int                 rv = SOC_E_NONE;
   1033 
   1034     SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config));
   1035 
   1036     uni_speed = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 
   1037                                   ETH_SPEEDf);
   1038 
   1039     switch(uni_speed) {
   1040     case SOC_UNIMAC_SPEED_10:
   1041 	*speed = 10;
   1042 	break;
   1043     case SOC_UNIMAC_SPEED_100:
   1044 	*speed = 100;
   1045 	break;
   1046     case SOC_UNIMAC_SPEED_1000:
   1047 	*speed = 1000;
   1048 	break;
   1049     case SOC_UNIMAC_SPEED_2500:
   1050 	*speed = 2500;
   1051 	break;
   1052     default:
   1053         rv = SOC_E_INTERNAL;
   1054     }
   1055 
   1056     LOG_VERBOSE(BSL_LS_SOC_GE,
   1057                 (BSL_META_U(unit,
   1058                             "mac_uni_speed_get: unit %d port %s speed=%dMb\n"),
   1059                  unit, SOC_PORT_NAME(unit, port),
   1060                  *speed));
   1061     return(rv);
   1062 }
   1063 
   1064 /*
   1065  * Function:
   1066  *      mac_uni_pause_set
   1067  * Purpose:
   1068  *      Configure UniMAC to transmit/receive pause frames.
   1069  * Parameters:
   1070  *      unit - StrataSwitch unit #.
   1071  *      port - StrataSwitch port # on unit.
   1072  *      pause_tx - Boolean: transmit pause, or -1 (don't change)
   1073  *      pause_rx - Boolean: receive pause, or -1 (don't change)
   1074  * Returns:
   1075  *      SOC_E_XXX
   1076  */
   1077 
   1078 STATIC  int
   1079 mac_uni_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx)
   1080 {
   1081     uint32 		command_config, ocommand_config;
   1082 
   1083     LOG_VERBOSE(BSL_LS_SOC_GE,
   1084                 (BSL_META_U(unit,
   1085                             "mac_uni_pause_set: unit %d port %s RX=%s TX=%s\n"),
   1086                  unit, SOC_PORT_NAME(unit, port),
   1087                  pause_rx ? "on" : "off",
   1088                  pause_tx ? "on" : "off"));
   1089 
   1090     if (pause_tx < 0 && pause_rx < 0) {
   1091         return SOC_E_NONE;
   1092     }
   1093 
   1094     if (IS_ST_PORT(unit, port)) {
   1095         if ((pause_tx == 0) && (pause_rx == 0)) {
   1096             return SOC_E_NONE;
   1097         } else {
   1098             /* Flow control cannot be enabled in HiGL mode */
   1099             return SOC_E_CONFIG;
   1100         }
   1101     }
   1102 
   1103     SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config));
   1104     ocommand_config = command_config;
   1105 
   1106     if (pause_rx >= 0) {
   1107         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config,
   1108                             PAUSE_IGNOREf, pause_rx ? 0 : 1);
   1109     }
   1110     if (pause_tx >= 0) {
   1111         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config,
   1112                             IGNORE_TX_PAUSEf, pause_tx ? 0 : 1);
   1113     }
   1114 
   1115     if (command_config == ocommand_config) {
   1116 	return SOC_E_NONE;
   1117     }
   1118 
   1119     /* First put the MAC in reset */
   1120     SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
   1121                                                    SOC_MAC_CONTROL_SW_RESET,
   1122                                                    TRUE));
   1123 
   1124     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 1);
   1125     SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config));
   1126 
   1127     /* Add 2usec delay before deasserting SW_RESET */
   1128     sal_udelay(2);
   1129 
   1130     /* Bring the MAC out of reset */
   1131     SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
   1132                                                    SOC_MAC_CONTROL_SW_RESET,
   1133                                                    FALSE));
   1134 
   1135     return SOC_E_NONE;
   1136 }
   1137 
   1138 /*
   1139  * Function:
   1140  *      mac_uni_pause_get
   1141  * Purpose:
   1142  *      Return current GE MAC transmit/receive pause frame configuration.
   1143  * Parameters:
   1144  *      unit - StrataSwitch unit #.
   1145  *      port - StrataSwitch port # on unit.
   1146  *      pause_tx - (OUT) TRUE is TX pause enabled.
   1147  *      pause_rx - (OUT) TRUE if obey RX pause enabled.
   1148  * Returns:
   1149  *      SOC_E_XXX
   1150  */
   1151 
   1152 STATIC int
   1153 mac_uni_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx)
   1154 {
   1155     uint32 		command_config;
   1156 
   1157     SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config));
   1158 
   1159     *pause_rx = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 
   1160                                   PAUSE_IGNOREf) ?  FALSE : TRUE;
   1161     *pause_tx = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 
   1162                                   IGNORE_TX_PAUSEf) ?  FALSE : TRUE;
   1163 
   1164     LOG_VERBOSE(BSL_LS_SOC_GE,
   1165                 (BSL_META_U(unit,
   1166                             "mac_uni_pause_get: unit %d port %s RX=%s TX=%s\n"),
   1167                  unit, SOC_PORT_NAME(unit, port),
   1168                  *pause_rx ? "on" : "off",
   1169                  *pause_tx ? "on" : "off"));
   1170     return SOC_E_NONE;
   1171 }
   1172 
   1173 /*
   1174  * Function:
   1175  *      mac_uni_pause_addr_set
   1176  * Purpose:
   1177  *      Set GE MAC source address for transmitted PAUSE frame
   1178  * Parameters:
   1179  *      unit - StrataSwitch unit #.
   1180  *      port - StrataSwitch port # on unit.
   1181  *      pause_mac - MAC address used for pause transmission.
   1182  * Returns:
   1183  *      SOC_E_XXX
   1184  */
   1185 
   1186 STATIC  int
   1187 mac_uni_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t pause_mac)
   1188 {
   1189     uint32 mac_0, mac_1;
   1190 
   1191     mac_0 = pause_mac[0] << 24 |
   1192             pause_mac[1] << 16 |
   1193             pause_mac[2] << 8 |
   1194             pause_mac[3] << 0;
   1195     mac_1 = pause_mac[4] << 8 |
   1196             pause_mac[5];
   1197 
   1198     SOC_IF_ERROR_RETURN(WRITE_MAC_0r(unit, port, mac_0));
   1199     SOC_IF_ERROR_RETURN(WRITE_MAC_1r(unit, port, mac_1));
   1200     
   1201     LOG_VERBOSE(BSL_LS_SOC_GE,
   1202                 (BSL_META_U(unit,
   1203                             "mac_uni_pause_addr_set: unit %d port %s "
   1204                              "MAC=<%02x:%02x:%02x:%02x:%02x:%02x>\n"),
   1205                  unit, SOC_PORT_NAME(unit, port),
   1206                  pause_mac[0], pause_mac[1], pause_mac[2],
   1207                  pause_mac[3], pause_mac[4], pause_mac[5]));
   1208     return SOC_E_NONE;
   1209 }
   1210 
   1211 /*
   1212  * Function:
   1213  *      mac_uni_pause_addr_get
   1214  * Purpose:
   1215  *      Return current GE MAC source address for transmitted PAUSE frames
   1216  * Parameters:
   1217  *      unit - StrataSwitch unit #.
   1218  *      port - StrataSwitch port # on unit.
   1219  *      pause_mac - (OUT) MAC address used for pause transmission.
   1220  * Returns:
   1221  *      SOC_E_XXX
   1222  */
   1223 
   1224 STATIC  int
   1225 mac_uni_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t pause_mac)
   1226 {
   1227     uint32 mac_0, mac_1;
   1228 
   1229     SOC_IF_ERROR_RETURN(READ_MAC_0r(unit, port, &mac_0));
   1230     SOC_IF_ERROR_RETURN(READ_MAC_1r(unit, port, &mac_1));
   1231 
   1232     pause_mac[0] = (uint8)(mac_0 >> 24);
   1233     pause_mac[1] = (uint8)(mac_0 >> 16);
   1234     pause_mac[2] = (uint8)(mac_0 >> 8);
   1235     pause_mac[3] = (uint8)(mac_0 >> 0);
   1236     pause_mac[4] = (uint8)(mac_1 >> 8);
   1237     pause_mac[5] = (uint8)(mac_1 >> 0);
   1238 
   1239     LOG_VERBOSE(BSL_LS_SOC_GE,
   1240                 (BSL_META_U(unit,
   1241                             "mac_uni_pause_addr_get: unit %d port %s "
   1242                              "MAC=<%02x:%02x:%02x:%02x:%02x:%02x>\n"),
   1243                  unit, SOC_PORT_NAME(unit, port),
   1244                  pause_mac[0], pause_mac[1], pause_mac[2],
   1245                  pause_mac[3], pause_mac[4], pause_mac[5]));
   1246     return SOC_E_NONE;
   1247 }
   1248 
   1249 /*
   1250  * Function:
   1251  *      mac_uni_loopback_set
   1252  * Purpose:
   1253  *      Set GE MAC into/out-of loopback mode
   1254  * Parameters:
   1255  *      unit - StrataSwitch unit #.
   1256  *      port - Port number on unit.
   1257  *      loopback - Boolean: true -> loopback mode, false -> normal operation
   1258  * Returns:
   1259  *      SOC_E_XXX
   1260  */
   1261 
   1262 STATIC int
   1263 mac_uni_loopback_set(int unit, soc_port_t port, int loopback)
   1264 {
   1265     uint32 		command_config, ocommand_config;
   1266     int         phy_lb = 0;
   1267 
   1268     LOG_VERBOSE(BSL_LS_SOC_GE,
   1269                 (BSL_META_U(unit,
   1270                             "mac_uni_loopback_set: unit %d port %s loopback=%s\n"),
   1271                  unit, SOC_PORT_NAME(unit, port),
   1272                  loopback ? "True" : "False"));
   1273 
   1274     /* The MAC loopback will not work when ENA_EXT_CONFIGf=1 because hardware puts MAC
   1275      * in reset state if link is down.
   1276      * A simple workaround is to put PHY in loopback mode to get the link. This brings
   1277      * MAC out of reset state, and then clears ENA_EXT_CONFIGf.
   1278      */
   1279     if (PHY_SGMII_AUTONEG_MODE(unit, port) && (!SOC_IS_HAWKEYE(unit))) {
   1280         SOC_IF_ERROR_RETURN(soc_phyctrl_loopback_get(unit, port, &phy_lb));
   1281 
   1282         SOC_IF_ERROR_RETURN(soc_phyctrl_loopback_set(unit,port,TRUE, TRUE));
   1283         sal_usleep(40000);
   1284         SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config));
   1285         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config,
   1286                           ENA_EXT_CONFIGf, loopback? 0 : 1);
   1287         SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config));
   1288         SOC_IF_ERROR_RETURN(soc_phyctrl_loopback_set(unit,port,phy_lb, TRUE));
   1289     }
   1290 
   1291     SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
   1292                                                    SOC_MAC_CONTROL_SW_RESET,
   1293                                                    TRUE));
   1294 
   1295     SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config));
   1296     ocommand_config = command_config;
   1297 
   1298     soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, LOOP_ENAf, 
   1299                       loopback ? 1 : 0);
   1300 
   1301     if (command_config != ocommand_config) {
   1302         SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config));
   1303     }
   1304 
   1305 #ifdef  BCM_GREYHOUND2_SUPPORT
   1306     if (SOC_IS_GREYHOUND2(unit) && loopback) {
   1307         /* GH2's QTCE ports need phy linkup signal to active MAC loopback */
   1308         SOC_IF_ERROR_RETURN(soc_phyctrl_loopback_get(unit, port, &phy_lb));
   1309         SOC_IF_ERROR_RETURN(soc_phyctrl_loopback_set(unit, port, TRUE, TRUE));
   1310         sal_usleep(1000);
   1311         SOC_IF_ERROR_RETURN(soc_phyctrl_loopback_set(unit, port, phy_lb, TRUE));
   1312         LOG_VERBOSE(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   1313                     "port %s need raise phy linkup signal for mac loopback!\n"),
   1314                     SOC_PORT_NAME(unit, port)));
   1315     }
   1316 #endif  /* BCM_GREYHOUND2_SUPPORT */
   1317 
   1318     SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port,
   1319                                                    SOC_MAC_CONTROL_SW_RESET,
   1320                                                    FALSE));
   1321 
   1322     return SOC_E_NONE;
   1323 }
   1324 
   1325 /*
   1326  * Function:
   1327  *      mac_uni_loopback_get
   1328  * Purpose:
   1329  *      Get current GE MAC loopback mode setting.
   1330  * Parameters:
   1331  *      unit - StrataSwitch unit #.
   1332  *      port - StrataSwitch port # on unit
   1333  *      loopback - (OUT) Boolean: true = loopback, false = normal
   1334  * Returns:
   1335  *      SOC_E_XXX
   1336  */
   1337 
   1338 STATIC int
   1339 mac_uni_loopback_get(int unit, soc_port_t port, int *loopback)
   1340 {
   1341     uint32 		command_config;
   1342 
   1343     SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config));
   1344 
   1345     *loopback = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 
   1346                                   LOOP_ENAf);
   1347 
   1348     LOG_VERBOSE(BSL_LS_SOC_GE,
   1349                 (BSL_META_U(unit,
   1350                             "mac_uni_loopback_get: unit %d port %s loopback=%s\n"),
   1351                  unit, SOC_PORT_NAME(unit, port),
   1352                  *loopback ? "True" : "False"));
   1353     return SOC_E_NONE;
   1354 }
   1355 
   1356 /*
   1357  * Function:
   1358  *      mac_uni_ability_get
   1359  * Purpose:
   1360  *      Return the UniMAC abilities
   1361  * Parameters:
   1362  *      unit - StrataSwitch Unit #.
   1363  *      port - StrataSwitch Port # on unit.
   1364  *      mode - (OUT) Mask of MAC abilities returned.
   1365  * Returns:
   1366  *      SOC_E_NONE
   1367  */
   1368 
   1369 STATIC  int
   1370 mac_uni_ability_get(int unit, soc_port_t port, soc_port_mode_t *mode)
   1371 {
   1372     COMPILER_REFERENCE(unit);
   1373     COMPILER_REFERENCE(port);
   1374 
   1375     if (SOC_IS_SC_CQ(unit) && 
   1376         (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_QGPORT)) {
   1377         /* 5682x/72x GE-only ports are fixed at 1G speed */
   1378         *mode = (SOC_PM_10MB_FD | SOC_PM_100MB_FD | SOC_PM_1000MB_FD |
   1379                  SOC_PM_SGMII | SOC_PM_LB_MAC | SOC_PM_PAUSE);
   1380     } else if (IS_ST_PORT(unit, port)) {
   1381         *mode = (SOC_PM_1000MB_FD | SOC_PM_2500MB_FD | SOC_PM_LB_MAC |
   1382                  SOC_PM_MII | SOC_PM_GMII);
   1383                 
   1384     } else {
   1385         *mode = (SOC_PM_10MB | SOC_PM_100MB | SOC_PM_1000MB_FD |
   1386                  SOC_PM_2500MB_FD |  SOC_PM_MII | SOC_PM_GMII |
   1387                  SOC_PM_LB_MAC | SOC_PM_PAUSE);
   1388     }
   1389 
   1390     LOG_VERBOSE(BSL_LS_SOC_GE,
   1391                 (BSL_META_U(unit,
   1392                             "mac_uni_ability_get: unit %d port %s mode=0x%x\n"),
   1393                  unit, SOC_PORT_NAME(unit, port),
   1394                  *mode));
   1395     return SOC_E_NONE;
   1396 }
   1397 
   1398 /*
   1399  * Function:
   1400  *      mac_uni_frame_max_set
   1401  * Description:
   1402  *      Set the maximum receive frame size for the GE port
   1403  * Parameters:
   1404  *      unit - Device number
   1405  *      port - Port number
   1406  *      size - Maximum frame size in bytes
   1407  * Return Value:
   1408  *      BCM_E_XXX
   1409  */
   1410 
   1411 STATIC int
   1412 mac_uni_frame_max_set(int unit, soc_port_t port, int size)
   1413 {
   1414     uint32 command_config, rx_ena;
   1415     int speed = 0;
   1416     LOG_VERBOSE(BSL_LS_SOC_GE,
   1417                 (BSL_META_U(unit,
   1418                             "mac_uni_frame_max_set: unit %d port %s size=%d\n"),
   1419                  unit, SOC_PORT_NAME(unit, port),
   1420                  size));
   1421 
   1422     if (IS_ST_PORT(unit, port)) {
   1423         size += 16; /* Account for 16 bytes of Higig2 header */
   1424     }
   1425 
   1426     SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config));
   1427     rx_ena = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, RX_ENAf);
   1428 
   1429     /* If Rx is enabled then disable RX */
   1430     if (rx_ena) {
   1431         /* Disable RX */
   1432         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 0);
   1433         SOC_IF_ERROR_RETURN
   1434             (WRITE_COMMAND_CONFIGr(unit, port, command_config));
   1435 
   1436         /* Wait for maximum frame receiption time(for 16K) based on speed */
   1437         SOC_IF_ERROR_RETURN(soc_mac_uni.md_speed_get(unit, port, &speed));
   1438         switch (speed) {
   1439         case 2500:
   1440             sal_usleep(55);
   1441             break;
   1442         case 1000:
   1443             sal_usleep(131);
   1444             break;
   1445         case 100:
   1446             sal_usleep(1310);
   1447             break;
   1448         case 10:
   1449             sal_usleep(13100);
   1450             break;
   1451         default:
   1452             break;
   1453         }
   1454     }
   1455 
   1456     SOC_IF_ERROR_RETURN(WRITE_FRM_LENGTHr(unit, port, size));
   1457 
   1458     /* if Rx was enabled before, restore it */
   1459     if (rx_ena) {
   1460         /* Enable RX */
   1461         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 1);
   1462         SOC_IF_ERROR_RETURN
   1463             (WRITE_COMMAND_CONFIGr(unit, port, command_config));
   1464     }
   1465 
   1466     return SOC_E_NONE;
   1467 }
   1468 
   1469 /*
   1470  * Function:
   1471  *      mac_uni_frame_max_get
   1472  * Description:
   1473  *      Set the maximum receive frame size for the GE port
   1474  * Parameters:
   1475  *      unit - Device number
   1476  *      port - Port number
   1477  *      size - Maximum frame size in bytes
   1478  * Return Value:
   1479  *      BCM_E_XXX
   1480  * Notes:
   1481  *      Depending on chip or port type the actual maximum receive frame size
   1482  *      might be slightly higher.
   1483  */
   1484 STATIC int
   1485 mac_uni_frame_max_get(int unit, soc_port_t port, int *size)
   1486 {
   1487     uint32  frame_length;
   1488  
   1489     SOC_IF_ERROR_RETURN(READ_FRM_LENGTHr(unit, port, &frame_length));
   1490 
   1491     *size = (int) frame_length;
   1492     if (IS_ST_PORT(unit, port)) {
   1493         *size -= 16;  /* Account for 16 bytes of Higig2 header */
   1494     }
   1495 
   1496     LOG_VERBOSE(BSL_LS_SOC_GE,
   1497                 (BSL_META_U(unit,
   1498                             "mac_uni_frame_max_get: unit %d port %s size=%d\n"),
   1499                  unit, SOC_PORT_NAME(unit, port),
   1500                  *size));
   1501     return SOC_E_NONE;
   1502 }
   1503 
   1504 /*
   1505  * Function:
   1506  *      mac_uni_ifg_set
   1507  * Description:
   1508  *      Sets the new ifg (Inter-frame gap) value
   1509  * Parameters:
   1510  *      unit   - Device number
   1511  *      port   - Port number
   1512  *      speed  - the speed for which the IFG is being set
   1513  *      duplex - the duplex for which the IFG is being set
   1514  *      ifg    - Inter-frame gap in bit-times
   1515  * Return Value:
   1516  *      BCM_E_XXX
   1517  * Notes:
   1518  *      The function makes sure the IFG value makes sense and updates the
   1519  *      IPG register in case the speed/duplex match the current settings
   1520  */
   1521 STATIC int
   1522 mac_uni_ifg_set(int unit, soc_port_t port, int speed,
   1523                 soc_port_duplex_t  duplex, int ifg)
   1524 {
   1525     int         cur_speed = 0;
   1526     int         cur_duplex;
   1527     int         ipg, real_ifg;
   1528     soc_ipg_t  *si = &SOC_PERSIST(unit)->ipg[port];
   1529 
   1530     LOG_VERBOSE(BSL_LS_SOC_GE,
   1531                 (BSL_META_U(unit,
   1532                             "mac_uni_ifg_set: unit %d port %s speed=%dMb duplex=%s "
   1533                              "ifg=%d\n"),
   1534                  unit, SOC_PORT_NAME(unit, port),
   1535                  speed, duplex == SOC_PORT_DUPLEX_FULL ? "Full" : "Half",
   1536                  ifg));
   1537 
   1538     /* Get IPG, check range of IFG */
   1539     SOC_IF_ERROR_RETURN(mac_uni_ifg_to_ipg(unit, port, speed, duplex,
   1540                                           ifg, &ipg));
   1541     SOC_IF_ERROR_RETURN(mac_uni_ipg_to_ifg(unit, port, speed, duplex,
   1542                                           ipg, &real_ifg));
   1543 
   1544     if (duplex == SOC_PORT_DUPLEX_FULL) {
   1545         if((speed != 10) && (speed != 100) &&
   1546            (speed != 1000) && (speed != 2500)) {
   1547             return SOC_E_PARAM;
   1548         }
   1549     } else {
   1550         if((speed != 10) && (speed != 100)) {
   1551             return SOC_E_PARAM;
   1552         }
   1553     }
   1554 
   1555     SOC_IF_ERROR_RETURN(mac_uni_duplex_get(unit, port, &cur_duplex));
   1556     SOC_IF_ERROR_RETURN(mac_uni_speed_get(unit, port, &cur_speed));
   1557 
   1558     if (cur_speed == speed &&
   1559         cur_duplex == (duplex == SOC_PORT_DUPLEX_FULL ? TRUE : FALSE)) {
   1560         /* First put the MAC in reset */
   1561         SOC_IF_ERROR_RETURN
   1562             (soc_mac_uni.md_control_set(unit, port, SOC_MAC_CONTROL_SW_RESET,
   1563                                         TRUE));
   1564         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, TX_IPG_LENGTHr, port,
   1565                                                    TX_IPG_LENGTHf, ipg));
   1566         /* Bring the MAC out of reset */
   1567         SOC_IF_ERROR_RETURN
   1568             (soc_mac_uni.md_control_set(unit, port, SOC_MAC_CONTROL_SW_RESET,
   1569                                         FALSE));
   1570 
   1571         /* HW update success. Update the SI */
   1572         if (duplex == SOC_PORT_DUPLEX_FULL) {
   1573             switch (speed) {
   1574                 case 10:
   1575                     si->fd_10 = real_ifg;
   1576                     break;
   1577                 case 100:
   1578                     si->fd_100 = real_ifg;
   1579                     break;
   1580                 case 1000:
   1581                     si->fd_1000 = real_ifg;
   1582                     break;
   1583                 case 2500:
   1584                     si->fd_2500 = real_ifg;
   1585                     break;
   1586                 /* coverity[dead_error_begin] */
   1587                 default:
   1588                     /* Should not reach */
   1589                     break;
   1590             }
   1591         } else {
   1592             switch (speed) {
   1593                 case 10:
   1594                     si->hd_10 = real_ifg;
   1595                     break;
   1596                 case 100:
   1597                     si->hd_100 = real_ifg;
   1598                     break;
   1599                 /* coverity[dead_error_begin] */
   1600                 default:
   1601                     /* Should not reach */
   1602                     break;
   1603             }
   1604         }
   1605     }
   1606 
   1607     return SOC_E_NONE;
   1608 }
   1609 
   1610 /*
   1611  * Function:
   1612  *      mac_uni_ifg_get
   1613  * Description:
   1614  *      Gets the ifg (Inter-frame gap) value for a specific speed/duplex
   1615  *      combination
   1616  * Parameters:
   1617  *      unit   - Device number
   1618  *      port   - Port number
   1619  *      speed  - the speed for which the IFG is being set
   1620  *      duplex - the duplex for which the IFG is being set
   1621  *      ifg    - Inter-frame gap in bit-times
   1622  * Return Value:
   1623  *      BCM_E_XXX
   1624  * Notes:
   1625  *      The function returns the REAL ifg value that will be (or is currently)
   1626  *      used by the chip, which might be different from the value initially
   1627  *      set by the ifg_set() call. The reason for that is that only certain
   1628  *      values are allowed.
   1629  */
   1630 STATIC int
   1631 mac_uni_ifg_get(int unit, soc_port_t port, int speed,
   1632                 soc_port_duplex_t  duplex, int *ifg)
   1633 {
   1634     soc_ipg_t  *si = &SOC_PERSIST(unit)->ipg[port];
   1635 
   1636     if (duplex == SOC_PORT_DUPLEX_FULL) {
   1637         switch (speed) {
   1638         case 10:
   1639             *ifg = si->fd_10;
   1640             break;
   1641         case 100:
   1642             *ifg = si->fd_100;
   1643             break;
   1644         case 1000:
   1645             *ifg = si->fd_1000;
   1646             break;
   1647         case 2500:
   1648             *ifg = si->fd_2500;
   1649             break;
   1650         default:
   1651             return SOC_E_PARAM;
   1652             break;
   1653         }
   1654     } else {
   1655         switch (speed) {
   1656         case 10:
   1657             *ifg = si->hd_10;
   1658             break;
   1659         case 100:
   1660             *ifg = si->hd_100;
   1661             break;
   1662        default:
   1663             return SOC_E_PARAM;
   1664             break;
   1665         }
   1666     }
   1667 
   1668     LOG_VERBOSE(BSL_LS_SOC_GE,
   1669                 (BSL_META_U(unit,
   1670                             "mac_uni_ifg_get: unit %d port %s speed=%dMb duplex=%s "
   1671                              "ifg=%d\n"),
   1672                  unit, SOC_PORT_NAME(unit, port),
   1673                  speed, duplex == SOC_PORT_DUPLEX_FULL ? "Full" : "Half",
   1674                  *ifg));
   1675     return SOC_E_NONE;
   1676 }
   1677 
   1678 /*
   1679  * Function:
   1680  *      mac_uni_interface_set
   1681  * Purpose:
   1682  *      Set GE MAC interface type
   1683  * Parameters:
   1684  *      unit - StrataSwitch unit #.
   1685  *      port - Port number on unit.
   1686  *      pif - one of SOC_PORT_IF_*
   1687  * Returns:
   1688  *      SOC_E_XXX
   1689  */
   1690 
   1691 STATIC int
   1692 mac_uni_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
   1693 {
   1694 #ifdef BROADCOM_DEBUG
   1695     LOG_VERBOSE(BSL_LS_SOC_GE,
   1696                 (BSL_META_U(unit,
   1697                             "mac_uni_interface_set: unit %d port %s interface=%s\n"),
   1698                  unit, SOC_PORT_NAME(unit, port),
   1699                  mac_uni_port_if_names[pif]));
   1700 #endif
   1701 
   1702     switch (pif) {
   1703     case SOC_PORT_IF_MII:
   1704     case SOC_PORT_IF_GMII:
   1705     case SOC_PORT_IF_SGMII:
   1706         return SOC_E_NONE;
   1707     default:
   1708         return SOC_E_UNAVAIL;
   1709     }
   1710 }
   1711 
   1712 /*
   1713  * Function:
   1714  *      mac_uni_interface_get
   1715  * Purpose:
   1716  *      Retrieve GE MAC interface type
   1717  * Parameters:
   1718  *      unit - StrataSwitch unit #.
   1719  *      port - StrataSwitch port # on unit.
   1720  *      pif - (OUT) one of SOC_PORT_IF_*
   1721  * Returns:
   1722  *      SOC_E_XXX
   1723  */
   1724 
   1725 STATIC int
   1726 mac_uni_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   1727 {
   1728     *pif = SOC_PORT_IF_GMII;
   1729 
   1730 #ifdef BROADCOM_DEBUG
   1731     LOG_VERBOSE(BSL_LS_SOC_GE,
   1732                 (BSL_META_U(unit,
   1733                             "mac_uni_interface_get: unit %d port %s interface=%s\n"),
   1734                  unit, SOC_PORT_NAME(unit, port),
   1735                  mac_uni_port_if_names[*pif]));
   1736 #endif
   1737     return SOC_E_NONE;
   1738 }
   1739 
   1740 /*
   1741  * Function:
   1742  *      mac_uni_encap_set
   1743  * Purpose:
   1744  *      Set the port encapsulation mode.
   1745  * Parameters:
   1746  *      unit - XGS unit #.
   1747  *      port - XGS port # on unit.
   1748  *      mode - encapsulation mode
   1749  * Returns:
   1750  *      SOC_E_XXX
   1751  */
   1752 STATIC int
   1753 mac_uni_encap_set(int unit, soc_port_t port, int mode)
   1754 {
   1755 #ifdef BROADCOM_DEBUG
   1756     LOG_VERBOSE(BSL_LS_SOC_GE,
   1757                 (BSL_META_U(unit,
   1758                             "mac_uni_encap_set: unit %d port %s encapsulation=%s\n"),
   1759                  unit, SOC_PORT_NAME(unit, port),
   1760                  mac_uni_encap_mode[mode]));
   1761 #endif
   1762 
   1763     if (mode == SOC_ENCAP_IEEE) {
   1764         return SOC_E_NONE;
   1765     }
   1766     return SOC_E_PARAM;
   1767 }
   1768 
   1769 /*
   1770  * Function:
   1771  *      mac_uni_encap_get
   1772  * Purpose:
   1773  *      Get the port encapsulation mode.
   1774  * Parameters:
   1775  *      unit - XGS unit #.
   1776  *      port - XGS port # on unit.
   1777  *      mode - (INT) encapsulation mode
   1778  * Returns:
   1779  *      SOC_E_XXX
   1780  */
   1781 STATIC int
   1782 mac_uni_encap_get(int unit, soc_port_t port, int *mode)
   1783 {
   1784     *mode = SOC_ENCAP_IEEE;
   1785 
   1786 #ifdef BROADCOM_DEBUG
   1787     LOG_VERBOSE(BSL_LS_SOC_GE,
   1788                 (BSL_META_U(unit,
   1789                             "mac_uni_encap_get: unit %d port %s encapsulation=%s\n"),
   1790                  unit, SOC_PORT_NAME(unit, port),
   1791                  mac_uni_encap_mode[*mode]));
   1792 #endif
   1793     return SOC_E_NONE;
   1794 }
   1795 
   1796 STATIC int
   1797 _mac_uni_sw_reset(int unit, soc_port_t port, int reset_assert)
   1798 {
   1799     uint32 command_config;
   1800     int reset_sleep_usec;
   1801 
   1802     if (SAL_BOOT_QUICKTURN) {
   1803         reset_sleep_usec = 50000;
   1804     } else {
   1805         /* Minimum of 5 clocks period with the slowest clock is required
   1806          * between each reset step.
   1807          *   10Mbps (2.5MHz) = 2000ns
   1808          *  100Mbps  (25MHz) = 200ns
   1809          * 1000Mbps (125MHz) = 40ns
   1810          * 2500Mbps (133MHz) = 37.5ns
   1811          */
   1812         reset_sleep_usec = 2;  /* choose max delay */
   1813     }
   1814  
   1815     SOC_IF_ERROR_RETURN
   1816         (READ_COMMAND_CONFIGr(unit, port, &command_config));
   1817     if (reset_assert) {
   1818         /* SIDE EFFECT: TX and RX are enabled when SW_RESET is set. */
   1819         /* Assert SW_RESET */
   1820         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 1);
   1821     } else {
   1822         /* Deassert SW_RESET */
   1823         soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 0);
   1824     }
   1825 
   1826     if (soc_feature(unit, soc_feature_unimac_reset_wo_clock)) {
   1827         if (reset_assert)
   1828             SOC_IF_ERROR_RETURN
   1829                 (soc_pgw_rx_fifo_reset(unit, port, TRUE));
   1830     }
   1831 
   1832     SOC_IF_ERROR_RETURN
   1833         (WRITE_COMMAND_CONFIGr(unit, port, command_config));
   1834 
   1835     sal_udelay(reset_sleep_usec);
   1836 
   1837     if (soc_feature(unit, soc_feature_unimac_reset_wo_clock)) {
   1838         if (!reset_assert)
   1839             SOC_IF_ERROR_RETURN
   1840                 (soc_pgw_rx_fifo_reset(unit, port, FALSE));
   1841     }
   1842 
   1843     return SOC_E_NONE;
   1844 }
   1845 
   1846 /*
   1847  * Function:
   1848  *      mac_uni_expected_rx_latency_get
   1849  * Purpose:
   1850  *      Get the UniMAC port expected Rx latency, part of determining LINK_DELAY
   1851  * Parameters:
   1852  *      unit - XGS unit #.
   1853  *      port - XGS port # on unit.
   1854  *      latency - (OUT) Latency in NS
   1855  * Returns:
   1856  *      SOC_E_XXX
   1857  */
   1858 STATIC int
   1859 mac_uni_expected_rx_latency_get(int unit, soc_port_t port, int *latency)
   1860 {
   1861     int speed = 0;
   1862     SOC_IF_ERROR_RETURN(mac_uni_speed_get(unit, port, &speed));
   1863 
   1864     switch (speed) {
   1865     case 10:
   1866         /* 10M value from KT-1370 */
   1867         *latency = 23200;
   1868         break;
   1869     case 100:
   1870         /* 100M value from KT-1370 */
   1871         *latency = 2320;
   1872         break;
   1873     case 1000:  /* GigE */
   1874         /* 1G value from KT-1370: 232ns */
   1875         /* 1G value from SDK-84155: 275ns */
   1876         *latency = 275;
   1877         break;
   1878 
   1879     default:
   1880         *latency = 0;
   1881         break;
   1882     }
   1883 
   1884     return SOC_E_NONE;
   1885 }
   1886 
   1887 /*
   1888  * Function:
   1889  *      mac_uni_control_set
   1890  * Purpose:
   1891  *      To configure MAC control properties.
   1892  * Parameters:
   1893  *      unit - XGS unit #.
   1894  *      port - XGS port # on unit.
   1895  *      type - MAC control property to set.
   1896  *      int  - New setting for MAC control.
   1897  * Returns:
   1898  *      SOC_E_XXX
   1899  */
   1900 STATIC int
   1901 mac_uni_control_set(int unit, soc_port_t port, soc_mac_control_t type,
   1902                     int value)
   1903 {
   1904     uint32 rval, fval, copy;
   1905 
   1906     LOG_VERBOSE(BSL_LS_SOC_GE,
   1907                 (BSL_META_U(unit,
   1908                             "mac_uni_control_set: unit %d port %s type=%d value=%d\n"),
   1909                  unit, SOC_PORT_NAME(unit, port),
   1910                  type, value));
   1911 
   1912     switch(type) {
   1913     case SOC_MAC_CONTROL_RX_SET:
   1914         SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &rval));
   1915         copy = rval;
   1916         soc_reg_field_set(unit, COMMAND_CONFIGr, &rval, RX_ENAf, value ? 1 : 0);
   1917         if (copy != rval) {
   1918             SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, rval));
   1919         }
   1920         break;
   1921     case SOC_MAC_CONTROL_TX_SET:
   1922         SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &rval));
   1923         copy = rval;
   1924         soc_reg_field_set(unit, COMMAND_CONFIGr, &rval, TX_ENAf, value ? 1 : 0);
   1925         if (copy != rval) {
   1926             SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, rval));
   1927         }
   1928         break;
   1929     case SOC_MAC_CONTROL_SW_RESET:
   1930     case SOC_MAC_CONTROL_DISABLE_PHY:
   1931         return _mac_uni_sw_reset(unit, port, value);
   1932 
   1933     case SOC_MAC_CONTROL_PFC_TYPE:
   1934         if (!SOC_REG_IS_VALID(unit, MAC_PFC_TYPEr)) {
   1935             return SOC_E_UNAVAIL;
   1936         }
   1937         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, MAC_PFC_TYPEr, port,
   1938                                                    PFC_ETH_TYPEf, value));
   1939         break;
   1940 
   1941     case SOC_MAC_CONTROL_PFC_OPCODE:
   1942         if (!SOC_REG_IS_VALID(unit, MAC_PFC_OPCODEr)) {
   1943             return SOC_E_UNAVAIL;
   1944         }
   1945         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, MAC_PFC_OPCODEr,
   1946                                                    port, PFC_OPCODEf, value));
   1947         break;
   1948 
   1949     case SOC_MAC_CONTROL_PFC_CLASSES:
   1950         if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
   1951             return SOC_E_UNAVAIL;
   1952         }
   1953         if (soc_reg_field_valid(unit, UNIMAC_PFC_CTRLr, PFC_EIGHT_CLASSf)) {
   1954             if (value == 16) {
   1955                 fval = 0;
   1956             } else if (value == 8) {
   1957                 fval = 1;
   1958             } else {
   1959                 return SOC_E_PARAM;
   1960             }
   1961             SOC_IF_ERROR_RETURN
   1962                 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port,
   1963                                         PFC_EIGHT_CLASSf, fval));
   1964         } else if (value != 8) {
   1965             return SOC_E_PARAM;
   1966         }
   1967         break;
   1968 
   1969     case SOC_MAC_CONTROL_PFC_MAC_DA_OUI:
   1970         if (!SOC_REG_IS_VALID(unit, MAC_PFC_DA_0r)) {
   1971             return SOC_E_UNAVAIL;
   1972         }
   1973         SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_0r(unit, port, &rval));
   1974         rval &= 0x00ffffff;
   1975         rval |= (value & 0x0000ff) << 24;
   1976         SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_DA_0r(unit, port, rval));
   1977 
   1978         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, MAC_PFC_DA_1r, port,
   1979                                                    PFC_MACDA_1f, value >> 8));
   1980         break;
   1981 
   1982     case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI:
   1983         if (!SOC_REG_IS_VALID(unit, MAC_PFC_DA_0r)) {
   1984             return SOC_E_UNAVAIL;
   1985         }
   1986         SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_0r(unit, port, &rval));
   1987         rval &= 0xff000000;
   1988         rval |= value & 0x00ffffff;
   1989         SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_DA_0r(unit, port, rval));
   1990         break;
   1991 
   1992     case SOC_MAC_CONTROL_PFC_RX_PASS:
   1993         if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit))
   1994                 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) {
   1995             SOC_IF_ERROR_RETURN
   1996                 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port,
   1997                                         RX_PASS_PFC_FRMf, value ? 1 : 0));
   1998         } else {
   1999             if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
   2000                 return SOC_E_UNAVAIL;
   2001             }
   2002             SOC_IF_ERROR_RETURN
   2003                 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port,
   2004                                         RX_PASS_PFC_FRMf, value ? 1 : 0));
   2005         }
   2006         break;
   2007 
   2008     case SOC_MAC_CONTROL_PFC_RX_ENABLE:
   2009         if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit))
   2010                 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) {
   2011             SOC_IF_ERROR_RETURN
   2012                 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, PFC_RX_ENBLf,
   2013                                         value ? 1 : 0));
   2014         } else {
   2015             if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
   2016                 return SOC_E_UNAVAIL;
   2017             }
   2018             SOC_IF_ERROR_RETURN
   2019                 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port, PFC_RX_ENBLf,
   2020                                         value ? 1 : 0));
   2021         }
   2022         break;
   2023 
   2024     case SOC_MAC_CONTROL_PFC_TX_ENABLE:
   2025         if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit))
   2026                 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) {
   2027             SOC_IF_ERROR_RETURN
   2028                 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, PFC_TX_ENBLf,
   2029                                         value ? 1 : 0));
   2030         } else {
   2031             if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
   2032                 return SOC_E_UNAVAIL;
   2033             }
   2034             SOC_IF_ERROR_RETURN
   2035                 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port, PFC_TX_ENBLf,
   2036                                         value ? 1 : 0));
   2037         }
   2038         break;
   2039 
   2040     case SOC_MAC_CONTROL_PFC_FORCE_XON:
   2041         if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit))
   2042                 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) {
   2043             SOC_IF_ERROR_RETURN
   2044                 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port,
   2045                                         FORCE_PFC_XONf, value ? 1 : 0));
   2046         } else {
   2047             if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
   2048                 return SOC_E_UNAVAIL;
   2049             }
   2050             SOC_IF_ERROR_RETURN
   2051                 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port,
   2052                                         FORCE_PFC_XONf, value ? 1 : 0));
   2053         }
   2054         break;
   2055 
   2056     case SOC_MAC_CONTROL_PFC_STATS_ENABLE:
   2057         if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit))
   2058                 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) {
   2059             SOC_IF_ERROR_RETURN
   2060                 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port,
   2061                                         PFC_STATS_ENf, value ? 1 : 0));
   2062         } else {
   2063             if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
   2064                 return SOC_E_UNAVAIL;
   2065             }
   2066             SOC_IF_ERROR_RETURN
   2067                 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port,
   2068                                         PFC_STATS_ENf, value ? 1 : 0));
   2069         }
   2070         break;
   2071 
   2072     case SOC_MAC_CONTROL_PFC_REFRESH_TIME:
   2073         if (!SOC_REG_IS_VALID(unit, MAC_PFC_REFRESH_CTRLr)) {
   2074             return SOC_E_UNAVAIL;
   2075         }
   2076         SOC_IF_ERROR_RETURN
   2077             (soc_reg_field32_modify(unit, MAC_PFC_REFRESH_CTRLr,
   2078                                     port, PFC_REFRESH_TIMERf, value));
   2079         break;
   2080 
   2081     case SOC_MAC_CONTROL_PFC_XOFF_TIME:
   2082         if (!SOC_REG_IS_VALID(unit, PFC_XOFF_TIMERr)) {
   2083             return SOC_E_UNAVAIL;
   2084         }
   2085         SOC_IF_ERROR_RETURN
   2086             (soc_reg_field32_modify(unit, PFC_XOFF_TIMERr,
   2087                                     port, PFC_XOFF_TIMERf, value));
   2088         break;
   2089 
   2090     case SOC_MAC_CONTROL_EEE_ENABLE:
   2091         if (!soc_feature(unit, soc_feature_eee)) {
   2092             return SOC_E_UNAVAIL;
   2093         }
   2094         if (!soc_reg_field_valid(unit, UMAC_EEE_CTRLr, EEE_ENf)) {
   2095             return SOC_E_UNAVAIL;
   2096         }
   2097         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, UMAC_EEE_CTRLr, 
   2098                                                    port, EEE_ENf, value));
   2099         break;
   2100 
   2101     case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME:
   2102         if (!soc_feature(unit, soc_feature_eee)) {
   2103             return SOC_E_UNAVAIL;
   2104         }
   2105 #if defined(BCM_HURRICANE2_SUPPORT)
   2106         if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   2107             SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   2108             if (SOC_REG_PORT_VALID(unit, MII_EEE_DELAY_ENTRY_TIMERr, port)) {
   2109                 SOC_IF_ERROR_RETURN(
   2110                     soc_reg_field32_modify(unit, MII_EEE_DELAY_ENTRY_TIMERr,
   2111                     port, MII_EEE_LPI_TIMERf, value));
   2112             }
   2113 
   2114             if (SOC_REG_PORT_VALID(unit, GMII_EEE_DELAY_ENTRY_TIMERr, port)) {
   2115                 SOC_IF_ERROR_RETURN(
   2116                     soc_reg_field32_modify(unit, GMII_EEE_DELAY_ENTRY_TIMERr,
   2117                     port, GMII_EEE_LPI_TIMERf, value));
   2118             }
   2119         } else
   2120 #endif
   2121         {
   2122             if (!soc_reg_field_valid(unit,
   2123                 EEE_DELAY_ENTRY_TIMERr, EEE_LPI_TIMERf)) {
   2124                 return SOC_E_UNAVAIL;
   2125             }
   2126             SOC_IF_ERROR_RETURN(
   2127                 soc_reg_field32_modify(unit, EEE_DELAY_ENTRY_TIMERr,
   2128                 port, EEE_LPI_TIMERf, value));
   2129         }
   2130         break;
   2131 
   2132     case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME:
   2133         if (!soc_feature(unit, soc_feature_eee)) {
   2134             return SOC_E_UNAVAIL;
   2135         }
   2136 #if defined(BCM_HURRICANE2_SUPPORT)
   2137         if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 
   2138             SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   2139             if (SOC_REG_PORT_VALID(unit, MII_EEE_WAKE_TIMERr, port)) {
   2140                 SOC_IF_ERROR_RETURN(
   2141                     soc_reg_field32_modify(unit, MII_EEE_WAKE_TIMERr,
   2142                     port, MII_EEE_WAKE_TIMERf, value));
   2143             }
   2144 
   2145             if (SOC_REG_PORT_VALID(unit, GMII_EEE_WAKE_TIMERr, port)) {
   2146                 SOC_IF_ERROR_RETURN(
   2147                     soc_reg_field32_modify(unit, GMII_EEE_WAKE_TIMERr,
   2148                     port, GMII_EEE_WAKE_TIMERf, value));
   2149             }
   2150         } else
   2151 #endif
   2152         {
   2153             if (!soc_reg_field_valid(unit, EEE_WAKE_TIMERr, EEE_WAKE_TIMERf)) {
   2154                 return SOC_E_UNAVAIL;
   2155             }
   2156             SOC_IF_ERROR_RETURN(
   2157                 soc_reg_field32_modify(unit, EEE_WAKE_TIMERr,
   2158                 port, EEE_WAKE_TIMERf, value));
   2159         }
   2160         break;
   2161 
   2162     case SOC_MAC_CONTROL_RX_VLAN_TAG_OUTER_TPID:
   2163         SOC_IF_ERROR_RETURN
   2164             (soc_reg_field32_modify(unit, TAG_0r, port,
   2165                                     FRM_TAG_0f, value));
   2166         if (soc_reg_field_valid(unit, TAG_0r, CONFIG_OUTER_TPID_ENABLEf)) {
   2167             SOC_IF_ERROR_RETURN
   2168                 (soc_reg_field32_modify(unit, TAG_0r, port,
   2169                      CONFIG_OUTER_TPID_ENABLEf, value ? 1 : 0));
   2170         }
   2171         break;
   2172 
   2173     case SOC_MAC_CONTROL_RX_VLAN_TAG_INNER_TPID:
   2174         SOC_IF_ERROR_RETURN
   2175             (soc_reg_field32_modify(unit, TAG_1r, port,
   2176                                     FRM_TAG_1f, value));
   2177         if (soc_reg_field_valid(unit, TAG_1r, CONFIG_INNER_TPID_ENABLEf)) {
   2178             SOC_IF_ERROR_RETURN
   2179                 (soc_reg_field32_modify(unit, TAG_1r, port,
   2180                      CONFIG_INNER_TPID_ENABLEf, value ? 1 : 0));
   2181         }
   2182         break;
   2183 
   2184     default:
   2185         return SOC_E_UNAVAIL;
   2186     }
   2187 
   2188     return SOC_E_NONE;
   2189 }
   2190 
   2191 /*
   2192  * Function:
   2193  *      mac_uni_control_get
   2194  * Purpose:
   2195  *      To get current MAC control setting.
   2196  * Parameters:
   2197  *      unit - XGS unit #.
   2198  *      port - XGS port # on unit.
   2199  *      type - MAC control property to set.
   2200  *      int  - New setting for MAC control.
   2201  * Returns:
   2202  *      SOC_E_XXX
   2203  */
   2204 STATIC int 
   2205 mac_uni_control_get(int unit, soc_port_t port, soc_mac_control_t type,
   2206                     int *value)
   2207 {
   2208     int rv;
   2209     uint32  rval, fval0, fval1;
   2210 
   2211     rv = SOC_E_NONE;
   2212 
   2213     switch (type) {
   2214     case SOC_MAC_CONTROL_RX_SET:
   2215         SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &rval));
   2216         *value = soc_reg_field_get(unit, COMMAND_CONFIGr, rval, RX_ENAf);
   2217         break;
   2218     case SOC_MAC_CONTROL_TX_SET:
   2219         SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &rval));
   2220         *value = soc_reg_field_get(unit, COMMAND_CONFIGr, rval, TX_ENAf);
   2221         break;
   2222     case SOC_MAC_CONTROL_TIMESTAMP_TRANSMIT:
   2223             {
   2224                 uint32 timestamp = 0;
   2225                 if (soc_feature(unit, soc_feature_timestamp_counter) &&
   2226                     soc_property_get(unit, spn_SW_TIMESTAMP_FIFO_ENABLE, 1)) {
   2227                     rv = soc_counter_timestamp_get(unit, port, &timestamp);
   2228                     if (rv != SOC_E_NOT_FOUND) {
   2229                         *value = (int)timestamp;
   2230                         return rv;
   2231                     }
   2232                 }
   2233 
   2234                 if (!SOC_REG_IS_VALID(unit, TS_STATUS_CNTRLr)) {
   2235                     return SOC_E_UNAVAIL;
   2236                 }
   2237                 SOC_IF_ERROR_RETURN(READ_TS_STATUS_CNTRLr(unit, port, &rval));
   2238                 if (soc_reg_field_get(unit, TS_STATUS_CNTRLr, rval, TX_TS_FIFO_EMPTYf)) {
   2239                     return SOC_E_EMPTY;
   2240                 }
   2241                 if (SOC_REG_IS_VALID(unit,TX_TS_SEQ_IDr)) {
   2242                     SOC_IF_ERROR_RETURN(READ_TX_TS_SEQ_IDr(unit, port, &rval));
   2243                     if (!soc_reg_field_get(unit, TX_TS_SEQ_IDr, rval, TSTS_VALIDf)) {
   2244                         return SOC_E_EMPTY;
   2245                     }
   2246                 }
   2247                 SOC_IF_ERROR_RETURN(READ_TX_TS_DATAr(unit, port, &rval));
   2248                 *value = (int) soc_reg_field_get(unit, TX_TS_DATAr, rval, TX_TS_DATAf);
   2249                 rv = SOC_E_NONE;
   2250             }
   2251             break;
   2252 
   2253     case SOC_MAC_CONTROL_PFC_TYPE:
   2254         if (!SOC_REG_IS_VALID(unit, MAC_PFC_TYPEr)) {
   2255             return SOC_E_UNAVAIL;
   2256         }
   2257         SOC_IF_ERROR_RETURN(READ_MAC_PFC_TYPEr(unit, port, &rval));
   2258         *value = soc_reg_field_get(unit, MAC_PFC_TYPEr, rval, PFC_ETH_TYPEf);
   2259         break;
   2260 
   2261     case SOC_MAC_CONTROL_PFC_OPCODE:
   2262         if (!SOC_REG_IS_VALID(unit, MAC_PFC_OPCODEr)) {
   2263             return SOC_E_UNAVAIL;
   2264         }
   2265         SOC_IF_ERROR_RETURN(READ_MAC_PFC_OPCODEr(unit, port, &rval));
   2266         *value = soc_reg_field_get(unit, MAC_PFC_OPCODEr, rval, PFC_OPCODEf);
   2267         break;
   2268 
   2269     case SOC_MAC_CONTROL_PFC_CLASSES:
   2270         if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
   2271             return SOC_E_UNAVAIL;
   2272         }
   2273         if (soc_reg_field_valid(unit, UNIMAC_PFC_CTRLr, PFC_EIGHT_CLASSf)) {
   2274             SOC_IF_ERROR_RETURN(READ_UNIMAC_PFC_CTRLr(unit, port, &rval));
   2275             *value = soc_reg_field_get(unit, UNIMAC_PFC_CTRLr, rval,
   2276                                        PFC_EIGHT_CLASSf) ? 8 : 16;
   2277         } else {
   2278             *value = 8;
   2279         }
   2280         break;
   2281 
   2282     case SOC_MAC_CONTROL_PFC_MAC_DA_OUI:
   2283         if (!SOC_REG_IS_VALID(unit, MAC_PFC_DA_0r)) {
   2284             return SOC_E_UNAVAIL;
   2285         }
   2286         SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_0r(unit, port, &rval));
   2287         fval0 = soc_reg_field_get(unit, MAC_PFC_DA_0r, rval, PFC_MACDA_0f);
   2288         SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_1r(unit, port, &rval));
   2289         fval1 = soc_reg_field_get(unit, MAC_PFC_DA_1r, rval, PFC_MACDA_1f);
   2290         *value = (fval0 >> 24) | (fval1 << 8);
   2291         break;
   2292 
   2293     case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI:
   2294         if (!SOC_REG_IS_VALID(unit, MAC_PFC_DA_0r)) {
   2295             return SOC_E_UNAVAIL;
   2296         }
   2297         SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_0r(unit, port, &rval));
   2298         *value = soc_reg_field_get(unit, MAC_PFC_DA_0r, rval, PFC_MACDA_0f) &
   2299             0x00ffffff;
   2300         break;
   2301 
   2302     case SOC_MAC_CONTROL_PFC_RX_PASS:
   2303         if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) 
   2304                 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) {
   2305             SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, &rval));
   2306             *value = soc_reg_field_get(unit, MAC_PFC_CTRLr, rval,
   2307                                        RX_PASS_PFC_FRMf);
   2308         } else {
   2309             if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
   2310                 return SOC_E_UNAVAIL;
   2311             }
   2312             SOC_IF_ERROR_RETURN(READ_UNIMAC_PFC_CTRLr(unit, port, &rval));
   2313             *value = soc_reg_field_get(unit, UNIMAC_PFC_CTRLr, rval,
   2314                                        RX_PASS_PFC_FRMf);
   2315         }
   2316         break;
   2317 
   2318     case SOC_MAC_CONTROL_PFC_RX_ENABLE:
   2319         if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) 
   2320                 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) {
   2321             SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, &rval));
   2322             *value = soc_reg_field_get(unit, MAC_PFC_CTRLr, rval, PFC_RX_ENBLf);
   2323         } else {
   2324             if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
   2325                 return SOC_E_UNAVAIL;
   2326             }
   2327             SOC_IF_ERROR_RETURN(READ_UNIMAC_PFC_CTRLr(unit, port, &rval));
   2328             *value = soc_reg_field_get(unit, UNIMAC_PFC_CTRLr, rval, PFC_RX_ENBLf);
   2329         }
   2330         break;
   2331 
   2332     case SOC_MAC_CONTROL_PFC_TX_ENABLE:
   2333         if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit))
   2334                 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) {
   2335             SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, &rval));
   2336             *value = soc_reg_field_get(unit, MAC_PFC_CTRLr, rval, PFC_TX_ENBLf);
   2337         } else {
   2338             if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
   2339                 return SOC_E_UNAVAIL;
   2340             }
   2341             SOC_IF_ERROR_RETURN(READ_UNIMAC_PFC_CTRLr(unit, port, &rval));
   2342             *value = soc_reg_field_get(unit, UNIMAC_PFC_CTRLr, rval, PFC_TX_ENBLf);
   2343         }
   2344         break;
   2345 
   2346     case SOC_MAC_CONTROL_PFC_FORCE_XON:
   2347         if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit))
   2348                 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) {
   2349             SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, &rval));
   2350             *value = soc_reg_field_get(unit, MAC_PFC_CTRLr, rval,
   2351                                        FORCE_PFC_XONf);
   2352         } else {
   2353             if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
   2354                 return SOC_E_UNAVAIL;
   2355             }
   2356             SOC_IF_ERROR_RETURN(READ_UNIMAC_PFC_CTRLr(unit, port, &rval));
   2357             *value = soc_reg_field_get(unit, UNIMAC_PFC_CTRLr, rval,
   2358                                        FORCE_PFC_XONf);
   2359         }
   2360         break;
   2361 
   2362     case SOC_MAC_CONTROL_PFC_STATS_ENABLE:
   2363         if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit))
   2364                 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) {
   2365             SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, &rval));
   2366             *value = soc_reg_field_get(unit, MAC_PFC_CTRLr, rval,
   2367                                        PFC_STATS_ENf);
   2368         } else {
   2369             if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) {
   2370                 return SOC_E_UNAVAIL;
   2371             }
   2372             SOC_IF_ERROR_RETURN(READ_UNIMAC_PFC_CTRLr(unit, port, &rval));
   2373             *value = soc_reg_field_get(unit, UNIMAC_PFC_CTRLr, rval,
   2374                                        PFC_STATS_ENf);
   2375         }
   2376         break;
   2377 
   2378     case SOC_MAC_CONTROL_PFC_REFRESH_TIME:
   2379         if (!SOC_REG_IS_VALID(unit, MAC_PFC_REFRESH_CTRLr)) {
   2380             return SOC_E_UNAVAIL;
   2381         }
   2382         SOC_IF_ERROR_RETURN(READ_MAC_PFC_REFRESH_CTRLr(unit, port, &rval));
   2383         *value = soc_reg_field_get(unit, MAC_PFC_REFRESH_CTRLr, rval,
   2384                                    PFC_REFRESH_TIMERf);
   2385         break;
   2386 
   2387     case SOC_MAC_CONTROL_PFC_XOFF_TIME:
   2388         if (!SOC_REG_IS_VALID(unit, PFC_XOFF_TIMERr)) {
   2389             return SOC_E_UNAVAIL;
   2390         }
   2391         SOC_IF_ERROR_RETURN(READ_PFC_XOFF_TIMERr(unit, port, &rval));
   2392         *value = soc_reg_field_get(unit, PFC_XOFF_TIMERr, rval,
   2393                                    PFC_XOFF_TIMERf);
   2394         break;
   2395 
   2396         case SOC_MAC_CONTROL_EEE_ENABLE:
   2397             if (!soc_feature(unit, soc_feature_eee)) {
   2398                 return SOC_E_UNAVAIL;
   2399             }
   2400             if (!soc_reg_field_valid(unit, UMAC_EEE_CTRLr, EEE_ENf)) {
   2401                 return SOC_E_UNAVAIL;
   2402             }
   2403             SOC_IF_ERROR_RETURN(READ_UMAC_EEE_CTRLr(unit, port, &rval));
   2404             *value = soc_reg_field_get(unit, UMAC_EEE_CTRLr, rval, EEE_ENf);
   2405             break;
   2406 
   2407         case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME:
   2408             if (!soc_feature(unit, soc_feature_eee)) {
   2409                 return SOC_E_UNAVAIL;
   2410             }
   2411 #if defined(BCM_HURRICANE2_SUPPORT)
   2412             if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 
   2413                 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   2414                 if (SOC_REG_PORT_VALID(
   2415                     unit, MII_EEE_DELAY_ENTRY_TIMERr, port)) {
   2416                     SOC_IF_ERROR_RETURN(
   2417                         READ_MII_EEE_DELAY_ENTRY_TIMERr(unit, port, &rval));
   2418                     *value = soc_reg_field_get(unit, MII_EEE_DELAY_ENTRY_TIMERr,
   2419                         rval, MII_EEE_LPI_TIMERf);
   2420                 } else if (SOC_REG_PORT_VALID(unit,
   2421                     GMII_EEE_DELAY_ENTRY_TIMERr, port)) {
   2422                     SOC_IF_ERROR_RETURN(
   2423                         READ_GMII_EEE_DELAY_ENTRY_TIMERr(unit, port, &rval));
   2424                     *value = soc_reg_field_get(unit,GMII_EEE_DELAY_ENTRY_TIMERr,
   2425                         rval, GMII_EEE_LPI_TIMERf);
   2426                 } else {
   2427                     return SOC_E_UNAVAIL;
   2428                 }
   2429             } else
   2430 #endif
   2431             {
   2432                 if (!soc_reg_field_valid(unit,
   2433                     EEE_DELAY_ENTRY_TIMERr, EEE_LPI_TIMERf)) {
   2434                     return SOC_E_UNAVAIL;
   2435                 }
   2436                 SOC_IF_ERROR_RETURN(
   2437                     READ_EEE_DELAY_ENTRY_TIMERr(unit, port, &rval));
   2438                 *value = soc_reg_field_get(unit, EEE_DELAY_ENTRY_TIMERr, rval,
   2439                         EEE_LPI_TIMERf);
   2440             }
   2441             break;
   2442 
   2443         case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME:
   2444             if (!soc_feature(unit, soc_feature_eee)) {
   2445                 return SOC_E_UNAVAIL;
   2446             }
   2447 #if defined(BCM_HURRICANE2_SUPPORT)
   2448             if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   2449                 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   2450                 if (SOC_REG_PORT_VALID(unit, MII_EEE_WAKE_TIMERr, port)) {
   2451                     SOC_IF_ERROR_RETURN(
   2452                         READ_MII_EEE_WAKE_TIMERr(unit, port, &rval));
   2453                     *value = soc_reg_field_get(unit, MII_EEE_WAKE_TIMERr,
   2454                         rval, MII_EEE_WAKE_TIMERf);
   2455                 } else if (
   2456                     SOC_REG_PORT_VALID(unit, GMII_EEE_WAKE_TIMERr, port)) {
   2457                     SOC_IF_ERROR_RETURN(
   2458                         READ_GMII_EEE_WAKE_TIMERr(unit, port, &rval));
   2459                     *value = soc_reg_field_get(unit, GMII_EEE_WAKE_TIMERr,
   2460                         rval, GMII_EEE_WAKE_TIMERf);
   2461                 } else {
   2462                     return SOC_E_UNAVAIL;
   2463                 }
   2464             } else
   2465 #endif
   2466             {
   2467                 if (!soc_reg_field_valid(unit,
   2468                     EEE_WAKE_TIMERr, EEE_WAKE_TIMERf)) {
   2469                     return SOC_E_UNAVAIL;
   2470                 }
   2471                 SOC_IF_ERROR_RETURN(READ_EEE_WAKE_TIMERr(unit, port, &rval));
   2472                 *value = soc_reg_field_get(unit, EEE_WAKE_TIMERr, rval,
   2473                         EEE_WAKE_TIMERf);
   2474             }
   2475             break;
   2476         
   2477         case SOC_MAC_CONTROL_FAULT_LOCAL_STATUS: 
   2478         case SOC_MAC_CONTROL_FAULT_REMOTE_STATUS: 
   2479             *value = 0;
   2480             break;
   2481 
   2482         case SOC_MAC_CONTROL_EXPECTED_RX_LATENCY:
   2483             SOC_IF_ERROR_RETURN(mac_uni_expected_rx_latency_get(unit, port, value));
   2484             break;
   2485 
   2486         case SOC_MAC_CONTROL_RX_VLAN_TAG_OUTER_TPID:
   2487             SOC_IF_ERROR_RETURN(READ_TAG_0r(unit, port, &rval));
   2488             *value = soc_reg_field_get(unit, TAG_0r, rval, FRM_TAG_0f);
   2489             break;
   2490 
   2491         case SOC_MAC_CONTROL_RX_VLAN_TAG_INNER_TPID:
   2492             SOC_IF_ERROR_RETURN(READ_TAG_1r(unit, port, &rval));
   2493             *value = soc_reg_field_get(unit, TAG_1r, rval, FRM_TAG_1f);
   2494             break;
   2495 
   2496         default:
   2497             return SOC_E_UNAVAIL;
   2498     }
   2499     LOG_VERBOSE(BSL_LS_SOC_GE,
   2500                 (BSL_META_U(unit,
   2501                             "mac_uni_control_get: unit %d port %s type=%d value=%d "
   2502                              "rv=%d\n"),
   2503                  unit, SOC_PORT_NAME(unit, port),
   2504                  type, *value, rv));
   2505     return rv;
   2506 }
   2507 
   2508 /*
   2509  * Function:
   2510  *      mac_uni_ability_local_get
   2511  * Purpose:
   2512  *      Return the UniMAC abilities
   2513  * Parameters:
   2514  *      unit - StrataSwitch Unit #.
   2515  *      port - StrataSwitch Port # on unit.
   2516  *      mode - (OUT) Mask of MAC abilities returned.
   2517  * Returns:
   2518  *      SOC_E_NONE
   2519  */
   2520 
   2521 STATIC  int
   2522 mac_uni_ability_local_get(int unit, soc_port_t port,
   2523                          soc_port_ability_t *ability)
   2524 {
   2525     COMPILER_REFERENCE(unit);
   2526     COMPILER_REFERENCE(port);
   2527 
   2528 #if defined(BCM_SCORPION_SUPPORT)
   2529     if (SOC_IS_SC_CQ(unit) && 
   2530         (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_QGPORT)) {
   2531         /* 5682x/72x GE-only ports are restricted */
   2532         ability->speed_half_duplex = 0; 
   2533         ability->speed_full_duplex =
   2534             SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB;
   2535     } else
   2536 #endif /* BCM_SCORPION_SUPPORT */
   2537 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
   2538         if (SOC_IS_TD_TT(unit) || SOC_IS_HURRICANE3(unit)) {
   2539         ability->speed_half_duplex =
   2540             SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB; 
   2541         ability->speed_full_duplex =
   2542             SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB;
   2543         if (SOC_CONTROL(unit)->info.port_speed_max[port] > 1000) {
   2544             ability->speed_full_duplex |= SOC_PA_SPEED_2500MB;
   2545         }
   2546     } else
   2547 #endif /* BCM_TRIDENT_SUPPORT */
   2548     {
   2549         ability->speed_half_duplex =
   2550             SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB; 
   2551         ability->speed_full_duplex =
   2552             SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB |
   2553             SOC_PA_SPEED_1000MB | SOC_PA_SPEED_2500MB;
   2554     }
   2555     ability->interface = SOC_PA_INTF_MII | SOC_PA_INTF_GMII; 
   2556     ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   2557     ability->medium    = SOC_PA_ABILITY_NONE;
   2558     ability->loopback  = SOC_PA_LB_MAC;
   2559     ability->flags     = SOC_PA_ABILITY_NONE;
   2560     ability->encap     = SOC_PA_ENCAP_IEEE;
   2561 
   2562     LOG_VERBOSE(BSL_LS_SOC_GE,
   2563                 (BSL_META_U(unit,
   2564                             "mac_uni_ability_local_get: unit %d port %s "
   2565                              "speed_half=0x%x speed_full=0x%x encap=0x%x pause=0x%x "
   2566                              "interface=0x%x medium=0x%x loopback=0x%x flags=0x%x\n"),
   2567                  unit, SOC_PORT_NAME(unit, port),
   2568                  ability->speed_half_duplex, ability->speed_full_duplex,
   2569                  ability->encap, ability->pause, ability->interface,
   2570                  ability->medium, ability->loopback, ability->flags));
   2571 
   2572     return (SOC_E_NONE);
   2573 }
   2574 
   2575 
   2576 /* Exported UniMAC driver structure */
   2577 mac_driver_t soc_mac_uni = {
   2578     "UniMAC Driver",                 /* drv_name */
   2579     mac_uni_init,                    /* md_init  */
   2580     mac_uni_enable_set,              /* md_enable_set */
   2581     mac_uni_enable_get,              /* md_enable_get */
   2582     mac_uni_duplex_set,              /* md_duplex_set */
   2583     mac_uni_duplex_get,              /* md_duplex_get */
   2584     mac_uni_speed_set,               /* md_speed_set */
   2585     mac_uni_speed_get,               /* md_speed_get */
   2586     mac_uni_pause_set,               /* md_pause_set */
   2587     mac_uni_pause_get,               /* md_pause_get */
   2588     mac_uni_pause_addr_set,          /* md_pause_addr_set */
   2589     mac_uni_pause_addr_get,          /* md_pause_addr_get */
   2590     mac_uni_loopback_set,            /* md_lb_set */
   2591     mac_uni_loopback_get,            /* md_lb_get */
   2592     mac_uni_interface_set,           /* md_interface_set */
   2593     mac_uni_interface_get,           /* md_interface_get */
   2594     mac_uni_ability_get,             /* md_ability_get */
   2595     mac_uni_frame_max_set,           /* md_frame_max_set */
   2596     mac_uni_frame_max_get,           /* md_frame_max_get */
   2597     mac_uni_ifg_set,                 /* md_ifg_set */
   2598     mac_uni_ifg_get,                 /* md_ifg_get */
   2599     mac_uni_encap_set,               /* md_encap_set */
   2600     mac_uni_encap_get,               /* md_encap_get */
   2601     mac_uni_control_set,             /* md_control_set */
   2602     mac_uni_control_get,             /* md_control_get */
   2603     mac_uni_ability_local_get,       /* md_ability_local_get */
   2604     NULL                             /* md_timesync_tx_info_get */
   2605 };
   2606 #endif /* BCM_UNIMAC_SUPPORT */