bnx2x_restart_autoneg(phy, params, 0);
        DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
 }
-static u8 bnx2x_link_settings_status(struct link_params *params,
-                                  struct link_vars *vars,
-                                  u32 gp_status,
-                                  u8 ext_phy_link_up)
+static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
+                                    struct link_params *params,
+                                    struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
-       u16 new_line_speed;
+       u16 new_line_speed , gp_status;
        u8 rc = 0;
        u32 ext_phy_type;
-       vars->link_status = 0;
+       /* Read gp_status */
+       CL45_RD_OVER_CL22(bp, phy,
+                               MDIO_REG_BANK_GP_STATUS,
+                               MDIO_GP_STATUS_TOP_AN_STATUS1,
+                               &gp_status);
+
        if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
                DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
                         gp_status);
                        return -EINVAL;
                }
 
-               /* Upon link speed change set the NIG into drain mode.
-               Comes to deals with possible FIFO glitch due to clk change
-               when speed is decreased without link down indicator */
-               if (new_line_speed != vars->line_speed) {
-                       if (!SINGLE_MEDIA_DIRECT(params) &&
-                           ext_phy_link_up) {
-                               DP(NETIF_MSG_LINK, "Internal link speed %d is"
-                                           " different than the external"
-                                           " link speed %d\n", new_line_speed,
-                                         vars->line_speed);
-                               vars->phy_link_up = 0;
-                               return 0;
-                       }
-                       REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
-                                   + params->port*4, 0);
-                       msleep(1);
-               }
                vars->line_speed = new_line_speed;
                vars->link_status |= LINK_STATUS_SERDES_LINK;
                ext_phy_type = params->phy[EXT_PHY1].type;
 }
 
 static u8 bnx2x_emac_program(struct link_params *params,
-                          u32 line_speed, u32 duplex)
+                            struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
        u8 port = params->port;
                     (EMAC_MODE_25G_MODE |
                     EMAC_MODE_PORT_MII_10M |
                     EMAC_MODE_HALF_DUPLEX));
-       switch (line_speed) {
+       switch (vars->line_speed) {
        case SPEED_10:
                mode |= EMAC_MODE_PORT_MII_10M;
                break;
 
        default:
                /* 10G not valid for EMAC */
-               DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n", line_speed);
+               DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
+                          vars->line_speed);
                return -EINVAL;
        }
 
-       if (duplex == DUPLEX_HALF)
+       if (vars->duplex == DUPLEX_HALF)
                mode |= EMAC_MODE_HALF_DUPLEX;
        bnx2x_bits_en(bp,
                    GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
                    mode);
 
-       bnx2x_set_led(params, LED_MODE_OPER, line_speed);
+       bnx2x_set_led(params, LED_MODE_OPER, vars->line_speed);
        return 0;
 }
 
+static u8 bnx2x_init_serdes(struct bnx2x_phy *phy,
+                           struct link_params *params,
+                           struct link_vars *vars)
+{
+       u8 rc;
+       vars->phy_flags |= PHY_SGMII_FLAG;
+       bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+       bnx2x_set_aer_mmd(params, phy);
+       rc = bnx2x_reset_unicore(params, phy, 1);
+       /* reset the SerDes and wait for reset bit return low */
+       if (rc != 0)
+               return rc;
+       bnx2x_set_aer_mmd(params, phy);
+
+       return rc;
+}
+
+static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
+                         struct link_params *params,
+                         struct link_vars *vars)
+{
+       u8 rc;
+       vars->phy_flags = PHY_XGXS_FLAG;
+       if ((phy->req_line_speed &&
+            ((phy->req_line_speed == SPEED_100) ||
+             (phy->req_line_speed == SPEED_10))) ||
+           (!phy->req_line_speed &&
+            (phy->speed_cap_mask >=
+             PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
+            (phy->speed_cap_mask <
+             PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
+            ))
+               vars->phy_flags |= PHY_SGMII_FLAG;
+       else
+               vars->phy_flags &= ~PHY_SGMII_FLAG;
+
+       bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+       bnx2x_set_aer_mmd(params, phy);
+       bnx2x_set_master_ln(params, phy);
+
+       rc = bnx2x_reset_unicore(params, phy, 0);
+       /* reset the SerDes and wait for reset bit return low */
+       if (rc != 0)
+               return rc;
+
+       bnx2x_set_aer_mmd(params, phy);
 
+       /* setting the masterLn_def again after the reset */
+       bnx2x_set_master_ln(params, phy);
+       bnx2x_set_swap_lanes(params, phy);
+
+       return rc;
+}
 /*****************************************************************************/
 /*                          External Phy section                            */
 /*****************************************************************************/
                      MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
 }
 
-static void bnx2x_ext_phy_reset(struct bnx2x_phy   *phy,
-                               struct link_params *params,
-                               struct link_vars   *vars)
-{
-       struct bnx2x *bp = params->bp;
-       DP(NETIF_MSG_LINK, "Port %x: bnx2x_ext_phy_reset\n", params->port);
-       /* The PHY reset is controled by GPIO 1
-        * Give it 1ms of reset pulse
-        */
-               switch (phy->type) {
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-                       DP(NETIF_MSG_LINK, "XGXS Direct\n");
-                       break;
-
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-                       DP(NETIF_MSG_LINK, "XGXS 8705/8706\n");
-
-                       /* Restore normal power mode*/
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-                                         params->port);
-
-                       /* HW reset */
-                       bnx2x_ext_phy_hw_reset(bp, params->port);
-
-                       bnx2x_cl45_write(bp, phy,
-                                      MDIO_PMA_DEVAD,
-                                      MDIO_PMA_REG_CTRL, 0xa040);
-                       break;
-
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-                       break;
-
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-
-                       /* Restore normal power mode*/
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                         MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-                                         params->port);
-
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-                                         MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-                                         params->port);
-
-                       bnx2x_cl45_write(bp, phy,
-                                      MDIO_PMA_DEVAD,
-                                      MDIO_PMA_REG_CTRL,
-                                      1<<15);
-                       break;
-
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-                       DP(NETIF_MSG_LINK, "XGXS 8072\n");
-
-                       /* Unset Low Power Mode and SW reset */
-                       /* Restore normal power mode*/
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-                                         params->port);
-
-                       bnx2x_cl45_write(bp, phy,
-                                      MDIO_PMA_DEVAD,
-                                      MDIO_PMA_REG_CTRL,
-                                      1<<15);
-                       break;
-
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-                       DP(NETIF_MSG_LINK, "XGXS 8073\n");
-
-                       /* Restore normal power mode*/
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-                                         params->port);
-
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-                                         params->port);
-                       break;
-
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-                       DP(NETIF_MSG_LINK, "XGXS SFX7101\n");
-
-                       /* Restore normal power mode*/
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-                                         params->port);
-
-                       /* HW reset */
-                       bnx2x_ext_phy_hw_reset(bp, params->port);
-                       break;
-
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
-                       /* Restore normal power mode*/
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                     MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-                                         params->port);
-
-                       /* HW reset */
-                       bnx2x_ext_phy_hw_reset(bp, params->port);
-
-                       bnx2x_cl45_write(bp, phy,
-                                      MDIO_PMA_DEVAD,
-                                      MDIO_PMA_REG_CTRL,
-                                      1<<15);
-                       break;
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
-                       msleep(1);
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-                                      MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-                                      params->port);
-                       break;
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
-                       DP(NETIF_MSG_LINK, "XGXS PHY Failure detected\n");
-                       break;
-               default:
-                       DP(NETIF_MSG_LINK, "BAD phy type 0x%x\n",
-                                phy->type);
-                       break;
-               }
-}
-
 static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
                                    u32 shmem_base, u32 spirom_ver)
 {
 
 static void bnx2x_sfp_set_transmitter(struct bnx2x *bp,
                                      struct bnx2x_phy *phy,
+                                     u8 port,
                                      u8 tx_en)
 {
        u16 val;
 
-       DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x\n", tx_en);
+       DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x\n",
+                tx_en, port);
        /* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/
        bnx2x_cl45_read(bp, phy,
                      MDIO_PMA_DEVAD,
         * In case of NOC feature is disabled and power is up, set GPIO control
         *  as input to enable listening of over-current indication
         */
-
-       if (!(params->feature_config_flags &
-             FEATURE_CONFIG_BCM8727_NOC) && is_power_up)
+       if (phy->flags & FLAGS_NOC)
+               return;
+       if (!(phy->flags &
+             FLAGS_NOC) && is_power_up)
                val = (1<<4);
        else
                /*
        if (rc == 0 ||
            (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
            PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-               bnx2x_sfp_set_transmitter(bp, phy, 1);
+               bnx2x_sfp_set_transmitter(bp, phy, params->port, 1);
        else
-               bnx2x_sfp_set_transmitter(bp, phy, 0);
+               bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
 
        return rc;
 }
                /* Disable transmit for this module */
                if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
                    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-                       bnx2x_sfp_set_transmitter(bp, phy, 0);
+                       bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
        }
 }
 
                        CL45_WR_OVER_CL22(bp, phy,
                                              bank,
                                              MDIO_RX0_RX_EQ_BOOST,
-                                             params->xgxs_config_rx[i]);
+                                         phy->rx_preemphasis[i]);
        }
 
        for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3;
                        CL45_WR_OVER_CL22(bp, phy,
                                              bank,
                                              MDIO_TX0_TX_DRIVER,
-                                             params->xgxs_config_tx[i]);
+                                         phy->tx_preemphasis[i]);
        }
 }
 
        }
 }
 
-static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
+static u16 bnx2x_wait_reset_complete(struct bnx2x *bp,
+                                    struct bnx2x_phy *phy)
 {
-       struct bnx2x *bp = params->bp;
-       u16 cnt;
-       u16 ctrl = 0;
-       u16 val = 0;
-       u8 rc = 0;
-       struct bnx2x_phy *phy = ¶ms->phy[EXT_PHY1];
-       if (vars->phy_flags & PHY_XGXS_FLAG) {
-               /* Make sure that the soft reset is off (expect for the 8072:
-                * due to the lock, it will be done inside the specific
-                * handling)
-                */
-               if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
-                   (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
-                  (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) &&
-                   (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
-                   (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
+       u16 cnt, ctrl;
                        /* Wait for soft reset to get cleared upto 1 sec */
                        for (cnt = 0; cnt < 1000; cnt++) {
                                bnx2x_cl45_read(bp, phy,
                        }
                        DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n",
                                 ctrl, cnt);
-               }
-
-               switch (phy->type) {
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-                       break;
+                       return 0;
+}
 
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
+static u8 bnx2x_8705_config_init(struct bnx2x_phy *phy,
+                                struct link_params *params,
+                                struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       DP(NETIF_MSG_LINK, "init 8705\n");
+       /* Restore normal power mode*/
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+                           MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+       /* HW reset */
+       bnx2x_ext_phy_hw_reset(bp, params->port);
+       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
+       bnx2x_wait_reset_complete(bp, phy);
                        DP(NETIF_MSG_LINK, "XGXS 8705\n");
 
                        bnx2x_cl45_write(bp, phy,
                        /* BCM8705 doesn't have microcode, hence the 0 */
                        bnx2x_save_spirom_version(bp, params->port,
                                                params->shmem_base, 0);
-                       break;
 
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
+                       return 0;
+}
+
+static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
+                                struct link_params *params,
+                                struct link_vars *vars)
+{
+       u16 cnt, val;
+       struct bnx2x *bp = params->bp;
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+                           MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+       /* HW reset */
+       bnx2x_ext_phy_hw_reset(bp, params->port);
+       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
+
+       bnx2x_wait_reset_complete(bp, phy);
                        /* Wait until fw is loaded */
                        for (cnt = 0; cnt < 100; cnt++) {
                                bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
                                        val &= ~0x7;
                                        /* Set control bits according to
                                        configuation */
-                                       val |= (params->xgxs_config_rx[i] &
+                                       val |= (phy->rx_preemphasis[i] &
                                                0x7);
                                        DP(NETIF_MSG_LINK, "Setting RX"
                                                 "Equalizer to BCM8706 reg 0x%x"
                        bnx2x_save_bcm_spirom_ver(bp, params->port,
                                                phy,
                                                params->shmem_base);
-                       break;
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+                       return 0;
+}
+
+static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
+                                struct link_params *params,
+                                struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
+       /* Restore normal power mode*/
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+                           MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+                           MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+
+       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
+       bnx2x_wait_reset_complete(bp, phy);
+
+       bnx2x_wait_reset_complete(bp, phy);
                        DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
                        bnx2x_8726_external_rom_boot(phy, params);
 
                             FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
                                DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
                                         "TX_CTRL2 0x%x\n",
-                                        params->xgxs_config_tx[0],
-                                        params->xgxs_config_tx[1]);
+                        phy->tx_preemphasis[0],
+                        phy->tx_preemphasis[1]);
                                bnx2x_cl45_write(bp, phy,
                                               MDIO_PMA_DEVAD,
                                               MDIO_PMA_REG_8726_TX_CTRL1,
-                                              params->xgxs_config_tx[0]);
+                                phy->tx_preemphasis[0]);
 
                                bnx2x_cl45_write(bp, phy,
                                               MDIO_PMA_DEVAD,
                                               MDIO_PMA_REG_8726_TX_CTRL2,
-                                              params->xgxs_config_tx[1]);
+                                phy->tx_preemphasis[1]);
                        }
-                       break;
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
+                       return 0;
+
+}
+
+static u8 bnx2x_8072_8073_config_init(struct bnx2x_phy *phy,
+                                struct link_params *params,
+                                struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       u16 val = 0;
+       u8 gpio_port;
+       DP(NETIF_MSG_LINK, "Init 8073\n");
+
+       gpio_port = params->port;
+       /* Restore normal power mode*/
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+                           MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
+
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+                           MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
+
                {
                        u16 tmp1;
                        u16 rx_alarm_ctrl_val;
                                bnx2x_807x_force_10G(bp, phy);
                                DP(NETIF_MSG_LINK,
                                        "Forced speed 10G on 807X\n");
-                               break;
+                               return 0;
                        } else {
                                bnx2x_cl45_write(bp, phy,
                                               MDIO_PMA_DEVAD,
                           "Advertise 1G=%x, 10G=%x\n",
                           ((val & (1<<5)) > 0),
                           ((val & (1<<7)) > 0));
-                       break;
+                       return 0;
                }
+}
 
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-               {
-                       u16 tmp1;
-                       u16 rx_alarm_ctrl_val;
-                       u16 lasi_ctrl_val;
+static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
+                                struct link_params *params,
+                                struct link_vars *vars)
+{
+       u16 tmp1, val, mod_abs;
+       u16 rx_alarm_ctrl_val;
+       u16 lasi_ctrl_val;
+       struct bnx2x *bp = params->bp;
+       /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
 
                        /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
 
-                       u16 mod_abs;
                        rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
                        lasi_ctrl_val = 0x0004;
-
+                       bnx2x_wait_reset_complete(bp, phy);
                        DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
                        /* enable LASI */
                        bnx2x_cl45_write(bp, phy,
                             FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
                                DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
                                         "TX_CTRL2 0x%x\n",
-                                        params->xgxs_config_tx[0],
-                                        params->xgxs_config_tx[1]);
+                                        phy->tx_preemphasis[0],
+                          phy->tx_preemphasis[1]);
                                bnx2x_cl45_write(bp, phy,
                                               MDIO_PMA_DEVAD,
                                               MDIO_PMA_REG_8727_TX_CTRL1,
-                                              params->xgxs_config_tx[0]);
+                                              phy->tx_preemphasis[0]);
 
                                bnx2x_cl45_write(bp, phy,
                                               MDIO_PMA_DEVAD,
                                               MDIO_PMA_REG_8727_TX_CTRL2,
-                                              params->xgxs_config_tx[1]);
+                                              phy->tx_preemphasis[1]);
                        }
 
-                       break;
-               }
+                       return 0;
+}
+
+static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy,
+                                struct link_params *params,
+                                struct link_vars *vars)
+{
+       u16 fw_ver1, fw_ver2, val;
+       struct bnx2x *bp = params->bp;
+       DP(NETIF_MSG_LINK, "Setting the SFX7101 LASI indication\n");
+
+       /* Restore normal power mode*/
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+                           MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+       /* HW reset */
+       bnx2x_ext_phy_hw_reset(bp, params->port);
 
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-               {
-                       u16 fw_ver1, fw_ver2;
                        DP(NETIF_MSG_LINK,
                                "Setting the SFX7101 LASI indication\n");
-
+                       bnx2x_wait_reset_complete(bp, phy);
                        bnx2x_cl45_write(bp, phy,
                                       MDIO_PMA_DEVAD,
                                       MDIO_PMA_REG_LASI_CTRL, 0x1);
                        bnx2x_save_spirom_version(params->bp, params->port,
                                                params->shmem_base,
                                                (u32)(fw_ver1<<16 | fw_ver2));
-                       break;
-               }
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
+                       return 0;
+}
+
+static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
+                                     struct link_params *params,
+                                     struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
                {
                        /* This phy uses the NIG latch mechanism since link
                                indication arrives through its LED4 and not via
                        u16 autoneg_val, an_1000_val, an_10_100_val, temp;
                        temp = vars->line_speed;
                        vars->line_speed = SPEED_10000;
+                       bnx2x_wait_reset_complete(bp, phy);
                        bnx2x_set_autoneg(phy, params, vars, 0);
                        bnx2x_program_serdes(phy, params, vars);
                        vars->line_speed = temp;
                        /* Save spirom version */
                        bnx2x_save_8481_spirom_version(phy, params,
                                                       params->shmem_base);
-                       break;
+                       return 0;
                }
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
-                       DP(NETIF_MSG_LINK,
-                                "XGXS PHY Failure detected 0x%x\n",
-                                phy->type);
-                       rc = -EINVAL;
-                       break;
+}
 
-               default:
-                       DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
-                          phy->type);
-                       break;
-               }
-       }
-       return rc;
+static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
+                                 struct link_params *params,
+                                 struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       u16 temp;
+       msleep(1);
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+                      MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+                      params->port);
+       msleep(200); /* 100 is not enough */
+
+       /**
+        * BCM84823 requires that XGXS links up first @ 10G for normal
+        * behavior
+        */
+       temp = vars->line_speed;
+       vars->line_speed = SPEED_10000;
+       bnx2x_set_autoneg(phy, params, vars, 0);
+       bnx2x_program_serdes(phy, params, vars);
+       vars->line_speed = temp;
+       return bnx2x_848xx_cmn_config_init(phy, params, vars);
 }
 
+static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy,
+                                struct link_params *params,
+                                struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       /* Restore normal power mode*/
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+                           MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+
+       /* HW reset */
+       bnx2x_ext_phy_hw_reset(bp, params->port);
+
+       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
+       return bnx2x_848xx_cmn_config_init(phy, params, vars);
+}
 static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
                                      struct link_params *params)
 {
 
                if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
                    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-                       bnx2x_sfp_set_transmitter(bp, phy, 0);
+                       bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
 
                if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
                        bnx2x_sfp_module_detection(phy, params);
        module plugged in/out */
 }
 
-
-static u8 bnx2x_ext_phy_is_link_up(struct bnx2x_phy *phy,
+static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy,
                                 struct link_params *params,
-                                struct link_vars *vars,
-                                u8 is_mi_int)
+                                struct link_vars *vars)
 {
-       struct bnx2x *bp = params->bp;
-       u16 val1 = 0, val2;
-       u16 rx_sd, pcs_status;
        u8 ext_phy_link_up = 0;
-
-       if (vars->phy_flags & PHY_XGXS_FLAG) {
-               switch (phy->type) {
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-                       DP(NETIF_MSG_LINK, "XGXS Direct\n");
-                       ext_phy_link_up = 1;
-                       break;
-
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
+       u16 val1, rx_sd;
+       struct bnx2x *bp = params->bp;
                        DP(NETIF_MSG_LINK, "XGXS 8705\n");
                        bnx2x_cl45_read(bp, phy,
                                      MDIO_WIS_DEVAD,
                                           ((val1 & (1<<8)) == 0));
                        if (ext_phy_link_up)
                                vars->line_speed = SPEED_10000;
-                       break;
+                       return ext_phy_link_up;
+}
 
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
+                                     struct link_params *params,
+                                     struct link_vars *vars)
+{
+       u8 link_up = 0;
+       u16 val1, val2, rx_sd, pcs_status;
+       struct bnx2x *bp = params->bp;
                        DP(NETIF_MSG_LINK, "XGXS 8706/8726\n");
                        /* Clear RX Alarm*/
                        bnx2x_cl45_read(bp, phy,
                         * bit 0 of pcs_status are set, or if the autoneg bit
                           1 is set
                         */
-                       ext_phy_link_up = ((rx_sd & pcs_status & 0x1) ||
-                                          (val2 & (1<<1)));
-                       if (ext_phy_link_up) {
-                               if (phy->type ==
-                                    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
-                                       /* If transmitter is disabled,
-                                       ignore false link up indication */
-                                       bnx2x_cl45_read(bp, phy,
-                                                  MDIO_PMA_DEVAD,
-                                                  MDIO_PMA_REG_PHY_IDENTIFIER,
-                                                  &val1);
-                                       if (val1 & (1<<15)) {
-                                               DP(NETIF_MSG_LINK, "Tx is "
-                                                           "disabled\n");
-                                               ext_phy_link_up = 0;
-                                               break;
-                                       }
-                               }
+                       link_up = ((rx_sd & pcs_status & 0x1) ||
+                                       (val2 & (1<<1)));
+                       if (link_up) {
                                if (val2 & (1<<1))
                                        vars->line_speed = SPEED_1000;
                                else
                                        vars->line_speed = SPEED_10000;
+                               bnx2x_ext_phy_resolve_fc(phy, params, vars);
+                               return link_up;
                        }
-                       break;
+                       return 0;
+}
 
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-               {
+static u8 bnx2x_8706_read_status(struct bnx2x_phy *phy,
+                                struct link_params *params,
+                                struct link_vars *vars)
+{
+       return bnx2x_8706_8726_read_status(phy, params, vars);
+}
+
+static u8 bnx2x_8726_read_status(struct bnx2x_phy *phy,
+                                struct link_params *params,
+                                struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       u16 val1;
+       u8 link_up = bnx2x_8706_8726_read_status(phy, params, vars);
+       if (link_up) {
+               bnx2x_cl45_read(bp, phy,
+                               MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
+                               &val1);
+               if (val1 & (1<<15)) {
+                       DP(NETIF_MSG_LINK, "Tx is disabled\n");
+                       link_up = 0;
+                       vars->line_speed = 0;
+               }
+       }
+       return link_up;
+}
+static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
+                                struct link_params *params,
+                                struct link_vars *vars)
+
+{
+       struct bnx2x *bp = params->bp;
+       u8 ext_phy_link_up = 0;
                        u16 link_status = 0;
-                       u16 rx_alarm_status;
+                       u16 rx_alarm_status, val1;
                        /* Check the LASI */
                        bnx2x_cl45_read(bp, phy,
                                      MDIO_PMA_DEVAD,
                         * If a module is present and there is need to check
                         * for over current
                         */
-                       if (!(params->feature_config_flags &
-                             FEATURE_CONFIG_BCM8727_NOC) &&
+                       if (!(phy->flags & FLAGS_NOC) &&
                            !(rx_alarm_status & (1<<5))) {
                                /* Check over-current using 8727 GPIO0 input*/
                                bnx2x_cl45_read(bp, phy,
                                                      MDIO_PMA_DEVAD,
                                                      MDIO_PMA_REG_RX_ALARM,
                                                      &rx_alarm_status);
-                                       break;
+                                       return ext_phy_link_up;
                                }
                        } /* Over current check */
 
                        if (val1 & (1<<15)) {
                                DP(NETIF_MSG_LINK, "Tx is disabled\n");
                                ext_phy_link_up = 0;
-                               break;
+                               return ext_phy_link_up;
                        }
 
                        bnx2x_cl45_read(bp, phy,
                                         "port %x: External link"
                                         " is down\n", params->port);
                        }
-                       break;
-               }
+                       return ext_phy_link_up;
 
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-               {
+}
+static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
+                                struct link_params *params,
+                                struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       u8 ext_phy_link_up = 0;
+       u16 val1, val2;
                        u16 link_status = 0;
                        u16 an1000_status = 0;
 
                                        if (bnx2x_8073_xaui_wa(bp, phy)
                                             != 0) {
                                                ext_phy_link_up = 0;
-                                               break;
+                                               return ext_phy_link_up;
                                        }
                                }
                                bnx2x_cl45_read(bp, phy,
                                }
                        }
 
-                       break;
-               }
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
+                       return ext_phy_link_up;
+}
+
+static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
+                                struct link_params *params,
+                                struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       u8 ext_phy_link_up;
+       u16 val1, val2;
                        bnx2x_cl45_read(bp, phy,
                                      MDIO_PMA_DEVAD,
                                      MDIO_PMA_REG_LASI_STATUS, &val2);
                                          val2,
                                         (val2 & (1<<14)));
                        }
-                       break;
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
+                       return ext_phy_link_up;
+}
+
+static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
+                                      struct link_params *params,
+                                      struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       u16 val1, val2;
+       u8 ext_phy_link_up = 0;
+
                        /* Check 10G-BaseT link status */
                        /* Check PMD signal ok */
                        bnx2x_cl45_read(bp, phy,
                                                (vars->duplex == DUPLEX_FULL));
                                }
                        }
-                       break;
-               default:
-                       DP(NETIF_MSG_LINK,
-                                "BAD SerDes ext_phy_config 0x%x\n",
-                                phy->type);
-                       ext_phy_link_up = 0;
-                       break;
-               }
-       }
-
-               /* Set SGMII mode for external phy */
-               if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
-                       if (vars->line_speed < SPEED_1000)
-                               vars->phy_flags |= PHY_SGMII_FLAG;
-                       else
-                               vars->phy_flags &= ~PHY_SGMII_FLAG;
-               }
-
-       return ext_phy_link_up;
+                       return ext_phy_link_up;
 }
+
 static void bnx2x_link_int_enable(struct link_params *params)
 {
        u8 port = params->port;
        }
 }
 
-static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
+static u8 bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+{
+       if (*len < 5)
+               return -EINVAL;
+       str[0] = (spirom_ver & 0xFF);
+       str[1] = (spirom_ver & 0xFF00) >> 8;
+       str[2] = (spirom_ver & 0xFF0000) >> 16;
+       str[3] = (spirom_ver & 0xFF000000) >> 24;
+       str[4] = '\0';
+       *len -= 5;
+       return 0;
+}
+
+static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len)
 {
        u8 *str_ptr = str;
        u32 mask = 0xf0000000;
        u8 shift = 8*4;
        u8 digit;
-       if (len < 10) {
+       if (*len < 10) {
                /* Need more than 10chars for this format */
                *str_ptr = '\0';
                return -EINVAL;
        return 0;
 }
 
+static u8 bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
+{
+       u8 status = 0;
+       u32 spirom_ver;
+       spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F);
+       status = bnx2x_format_ver(spirom_ver, str, len);
+       return status;
+}
+
+static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+{
+       str[0] = '\0';
+       (*len)--;
+       return 0;
+}
+
 u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
                              u8 *version, u16 len)
 {
        struct bnx2x *bp;
-       u32 ext_phy_type = 0;
        u32 spirom_ver = 0;
-       u8 status;
-
+       u8 status = 0;
+       u8 *ver_p = version;
        if (version == NULL || params == NULL)
                return -EINVAL;
        bp = params->bp;
 
-       spirom_ver = REG_RD(bp, params->shmem_base +
-                  offsetof(struct shmem_region,
-                           port_mb[params->port].ext_phy_fw_version));
-
-       status = 0;
-       /* reset the returned value to zero */
-       ext_phy_type = params->phy[EXT_PHY1].type;
-       switch (ext_phy_type) {
-       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-
-               if (len < 5)
-                       return -EINVAL;
-
-               version[0] = (spirom_ver & 0xFF);
-               version[1] = (spirom_ver & 0xFF00) >> 8;
-               version[2] = (spirom_ver & 0xFF0000) >> 16;
-               version[3] = (spirom_ver & 0xFF000000) >> 24;
-               version[4] = '\0';
-
-               break;
-       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-               status = bnx2x_format_ver(spirom_ver, version, len);
-               break;
-       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
-       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
-               spirom_ver = ((spirom_ver & 0xF80) >> 7) << 16 |
-                       (spirom_ver & 0x7F);
-               status = bnx2x_format_ver(spirom_ver, version, len);
-               break;
-       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
-               version[0] = '\0';
-               break;
-
-       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
-               DP(NETIF_MSG_LINK, "bnx2x_get_ext_phy_fw_version:"
-                                   " type is FAILURE!\n");
-               status = -EINVAL;
-               break;
+       /* Extract first external phy*/
+       version[0] = '\0';
+       spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr);
 
-       default:
-               break;
-       }
+       if (params->phy[EXT_PHY1].format_fw_ver)
+               status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver,
+                                                             ver_p,
+                                                             &len);
        return status;
 }
 
        }
 }
 
-static void bnx2x_ext_phy_loopback(struct bnx2x_phy *phy,
-                                  struct link_params *params)
+static void bnx2x_8726_config_loopback(struct bnx2x_phy *phy,
+                                      struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
+       DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n");
+       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0001);
+}
 
-       if (params->switch_cfg == SWITCH_CFG_10G) {
-
-               /* CL37 Autoneg Enabled */
-               switch (phy->type) {
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
-                       DP(NETIF_MSG_LINK,
-                               "ext_phy_loopback: We should not get here\n");
-                       break;
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
-                       DP(NETIF_MSG_LINK, "ext_phy_loopback: 8705\n");
-                       break;
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-                       DP(NETIF_MSG_LINK, "ext_phy_loopback: 8706\n");
-                       break;
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-                       DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n");
-                       bnx2x_cl45_write(bp, phy,
-                                      MDIO_PMA_DEVAD,
-                                      MDIO_PMA_REG_CTRL,
-                                      0x0001);
-                       break;
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-                       /* SFX7101_XGXS_TEST1 */
-                       bnx2x_cl45_write(bp, phy,
-                                      MDIO_XS_DEVAD,
-                                      MDIO_XS_SFX7101_XGXS_TEST1,
-                                      0x100);
-                       DP(NETIF_MSG_LINK,
-                               "ext_phy_loopback: set ext phy loopback\n");
-                       break;
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-
-                       break;
-               } /* switch external PHY type */
-       }
+static void bnx2x_7101_config_loopback(struct bnx2x_phy *phy,
+                                      struct link_params *params)
+{
+       struct bnx2x *bp = params->bp;
+       /* SFX7101_XGXS_TEST1 */
+       bnx2x_cl45_write(bp, phy,
+                        MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
 }
 /*
  *------------------------------------------------------------------------
                              MDIO_GP_STATUS_TOP_AN_STATUS1,
                              &gp_status);
        /* link is up only if both local phy and external phy are up */
-       if ((gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) &&
-           bnx2x_ext_phy_is_link_up(¶ms->phy[EXT_PHY1], params, vars, 1))
-               return 0;
+       if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
+               u8 ext_phy_link_up = 1;
+               struct link_vars temp_vars;
+               if (params->phy[EXT_PHY1].read_status)
+                       ext_phy_link_up &=
+                               params->phy[EXT_PHY1].read_status(
+                                               ¶ms->phy[EXT_PHY1],
+                                               params, &temp_vars);
+               if (ext_phy_link_up)
+                       return 0;
+       }
 
        return -ESRCH;
 }
        struct bnx2x *bp = params->bp;
        u8 port = params->port;
        u8 rc = 0;
-       u8 non_ext_phy;
+       u8 phy_index, non_ext_phy;
        struct bnx2x_phy *ext_phy = ¶ms->phy[EXT_PHY1];
        struct bnx2x_phy *int_phy = ¶ms->phy[INT_PHY];
        /* Activate the external PHY */
-       bnx2x_ext_phy_reset(ext_phy, params, vars);
 
        bnx2x_set_aer_mmd(params, int_phy);
 
        }
 
        if (!non_ext_phy)
-               rc |= bnx2x_ext_phy_init(params, vars);
+               for (phy_index = EXT_PHY1; phy_index < params->num_phys;
+                     phy_index++) {
+                       params->phy[phy_index].config_init(
+                               ¶ms->phy[phy_index],
+                               params, vars);
+               }
 
        bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
                     (NIG_STATUS_XGXS0_LINK10G |
        return rc;
 }
 
+static void set_phy_vars(struct link_params *params)
+{
+       struct bnx2x *bp = params->bp;
+       u8 actual_phy_idx, phy_index;
+
+       for (phy_index = INT_PHY; phy_index < params->num_phys;
+             phy_index++) {
+
+               actual_phy_idx = phy_index;
+               params->phy[actual_phy_idx].req_flow_ctrl  =
+                       params->req_flow_ctrl;
+
+               params->phy[actual_phy_idx].req_line_speed =
+                       params->req_line_speed;
+
+               params->phy[actual_phy_idx].speed_cap_mask =
+                       params->speed_cap_mask;
+
+               params->phy[actual_phy_idx].req_duplex =
+                       params->req_duplex;
+
+               DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
+                          " speed_cap_mask %x\n",
+                          params->phy[actual_phy_idx].req_flow_ctrl,
+                          params->phy[actual_phy_idx].req_line_speed,
+                          params->phy[actual_phy_idx].speed_cap_mask);
+       }
+}
+
 u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
        vars->duplex = DUPLEX_FULL;
        vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
        vars->mac_type = MAC_TYPE_NONE;
-
-       if (params->switch_cfg ==  SWITCH_CFG_1G) {
-               params->phy[INT_PHY].type =
-                               PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT;
-               vars->phy_flags = PHY_SERDES_FLAG;
-       } else {
-               params->phy[INT_PHY].type =
-                               PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT;
-               vars->phy_flags = PHY_XGXS_FLAG;
-       }
-       params->phy[INT_PHY].mdio_ctrl =
-               bnx2x_get_emac_base(bp,
-                                   params->phy[INT_PHY].type, params->port);
-       if (XGXS_EXT_PHY_TYPE(params->ext_phy_config) !=
-            PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
-               params->phy[EXT_PHY1].type =
-                       XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-               params->phy[EXT_PHY1].addr =
-                       XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-               params->phy[EXT_PHY1].mdio_ctrl =
-                       bnx2x_get_emac_base(bp, params->phy[EXT_PHY1].type,
-                                           params->port);
-       }
+       vars->phy_flags = 0;
 
        /* disable attentions */
        bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
 
        bnx2x_emac_init(params, vars);
 
+       if (params->num_phys == 0) {
+               DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
+               return -EINVAL;
+       }
+       set_phy_vars(params);
+
+       DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
        if (CHIP_REV_IS_FPGA(bp)) {
 
                vars->link_up = 1;
                bnx2x_phy_deassert(params, vars->phy_flags);
                /* set bmac loopback */
                bnx2x_emac_enable(params, vars, 1);
-               bnx2x_emac_program(params, vars->line_speed,
-                                             vars->duplex);
+               bnx2x_emac_program(params, vars);
                REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
                    params->port*4, 0);
 
                val = REG_RD(bp,
                                 NIG_REG_XGXS0_CTRL_PHY_ADDR+
                                 params->port*0x18);
-               params->phy_addr = (u8)val;
-               params->phy[INT_PHY].addr = (u8)val;
+
                bnx2x_phy_deassert(params, vars->phy_flags);
                bnx2x_link_initialize(params, vars);
 
 
                if (params->loopback_mode == LOOPBACK_XGXS_10) {
                        /* set 10G XGXS loopback */
-                       bnx2x_set_xgxs_loopback(¶ms->phy[INT_PHY],
-                                               params, 1);
+                       params->phy[INT_PHY].config_loopback(
+                               ¶ms->phy[INT_PHY],
+                               params);
+
                } else {
                        /* set external phy loopback */
-                       bnx2x_ext_phy_loopback(¶ms->phy[INT_PHY],
+                       u8 phy_index;
+                       for (phy_index = EXT_PHY1;
+                             phy_index < params->num_phys; phy_index++) {
+                               if (params->phy[phy_index].config_loopback)
+                                       params->phy[phy_index].config_loopback(
+                                               ¶ms->phy[phy_index],
                                               params);
+                       }
                }
 
                REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
        } else
        /* No loopback */
        {
+               if (params->switch_cfg == SWITCH_CFG_10G)
+                       vars->phy_flags = PHY_XGXS_FLAG;
                bnx2x_phy_deassert(params, vars->phy_flags);
-               switch (params->switch_cfg) {
-               case SWITCH_CFG_1G:
-                       vars->phy_flags |= PHY_SERDES_FLAG;
-                       if ((params->ext_phy_config &
-                            PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) ==
-                            PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482) {
-                               vars->phy_flags |= PHY_SGMII_FLAG;
-                       }
-
-                       val = REG_RD(bp,
-                                        NIG_REG_SERDES0_CTRL_PHY_ADDR+
-                                        params->port*0x10);
-
-                       params->phy_addr = (u8)val;
-
-                       break;
-               case SWITCH_CFG_10G:
-                       vars->phy_flags |= PHY_XGXS_FLAG;
-                       val = REG_RD(bp,
-                                NIG_REG_XGXS0_CTRL_PHY_ADDR+
-                                params->port*0x18);
-                       params->phy_addr = (u8)val;
-
-                       break;
-               default:
-                       DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
-                       return -EINVAL;
-               }
-               DP(NETIF_MSG_LINK, "Phy address = 0x%x\n", params->phy_addr);
-               params->phy[INT_PHY].addr = params->phy_addr;
                bnx2x_link_initialize(params, vars);
                msleep(30);
                bnx2x_link_int_enable(params);
 }
 
 
-static void bnx2x_8726_reset_phy(struct bnx2x *bp,
-                                struct bnx2x_phy *phy)
+static void bnx2x_8726_link_reset(struct bnx2x_phy *phy,
+                                 struct link_params *params)
 {
-       DP(NETIF_MSG_LINK, "bnx2x_8726_reset_phy\n");
+       struct bnx2x *bp = params->bp;
+       DP(NETIF_MSG_LINK, "bnx2x_8726_link_reset port %d\n", params->port);
        /* Set serial boot control for external load */
        bnx2x_cl45_write(bp, phy,
-                      MDIO_PMA_DEVAD,
-                      MDIO_PMA_REG_GEN_CTRL, 0x0001);
+                        MDIO_PMA_DEVAD,
+                        MDIO_PMA_REG_GEN_CTRL, 0x0001);
+}
+
+static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
+                                 struct link_params *params)
+{
+       struct bnx2x *bp = params->bp;
+       /* Disable Transmitter */
+       bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+}
+static void bnx2x_8073_link_reset(struct bnx2x_phy *phy,
+                                 struct link_params *params)
+{
+       struct bnx2x *bp = params->bp;
+       u8 gpio_port;
+       gpio_port = params->port;
+       DP(NETIF_MSG_LINK, "Setting 8073 port %d into low power mode\n",
+          gpio_port);
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+                           MISC_REGISTERS_GPIO_OUTPUT_LOW,
+                           gpio_port);
+}
+static void bnx2x_8481_link_reset(struct bnx2x_phy *phy,
+                                       struct link_params *params)
+{
+       bnx2x_cl45_write(params->bp, phy,
+                        MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
+       bnx2x_cl45_write(params->bp, phy,
+                        MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1);
+}
+
+static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
+                                  struct link_params *params)
+{
+       struct bnx2x *bp = params->bp;
+       u8 port = params->port;
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+                           MISC_REGISTERS_GPIO_OUTPUT_LOW,
+                           port);
+}
+
+static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy,
+                                       struct link_params *params)
+{
+       struct bnx2x *bp = params->bp;
+       u8 gpio_port;
+       /* HW reset */
+       gpio_port = params->port;
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+                           MISC_REGISTERS_GPIO_OUTPUT_LOW,
+                           gpio_port);
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+                           MISC_REGISTERS_GPIO_OUTPUT_LOW,
+                           gpio_port);
+       DP(NETIF_MSG_LINK, "reset external PHY\n");
+}
+
+static void bnx2x_int_link_reset(struct bnx2x_phy *phy,
+                                struct link_params *params)
+{
+       /* reset the SerDes/XGXS */
+       REG_WR(params->bp, GRCBASE_MISC +
+                    MISC_REGISTERS_RESET_REG_3_CLEAR,
+                    (0x1ff << (params->port*16)));
 }
 
 u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
 {
        struct bnx2x *bp = params->bp;
 
-       u8 port = params->port;
+       u8 phy_index, port = params->port;
 
-       u32 val = REG_RD(bp, params->shmem_base +
-                            offsetof(struct shmem_region, dev_info.
-                                     port_feature_config[params->port].
-                                     config));
        DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port);
        /* disable attentions */
        vars->link_status = 0;
         /* clear link led */
        bnx2x_set_led(params, LED_MODE_OFF, 0);
        if (reset_ext_phy) {
-               struct bnx2x_phy *phy = ¶ms->phy[EXT_PHY1];
-               switch (phy->type) {
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-                       break;
-
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-               {
-
-                       /* Disable Transmitter */
-                       if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-                           PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-                               bnx2x_sfp_set_transmitter(bp, phy, 0);
-                       break;
-               }
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-                       DP(NETIF_MSG_LINK, "Setting 8073 port %d into "
-                                "low power mode\n",
-                                port);
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                         MISC_REGISTERS_GPIO_OUTPUT_LOW,
-                                         port);
-                       break;
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-               {
-                       /* Set soft reset */
-                       bnx2x_8726_reset_phy(bp, phy);
-                       break;
-               }
-               case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
-               {
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-                                      MISC_REGISTERS_GPIO_OUTPUT_LOW,
-                                      params->port);
-                       break;
-               }
-               default:
-                       /* HW reset */
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-                                         MISC_REGISTERS_GPIO_OUTPUT_LOW,
-                                         port);
-                       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-                                         MISC_REGISTERS_GPIO_OUTPUT_LOW,
-                                         port);
-                       DP(NETIF_MSG_LINK, "reset external PHY\n");
+               for (phy_index = EXT_PHY1; phy_index < params->num_phys;
+                     phy_index++) {
+                       if (params->phy[phy_index].link_reset)
+                               params->phy[phy_index].link_reset(
+                                       ¶ms->phy[phy_index],
+                                       params);
                }
        }
-       /* reset the SerDes/XGXS */
-       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
-              (0x1ff << (port*16)));
 
+       if (params->phy[INT_PHY].link_reset)
+               params->phy[INT_PHY].link_reset(
+                       ¶ms->phy[INT_PHY], params);
        /* reset BigMac */
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
               (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
 
 static u8 bnx2x_update_link_up(struct link_params *params,
                             struct link_vars *vars,
-                            u8 link_10g, u32 gp_status)
+                            u8 link_10g)
 {
        struct bnx2x *bp = params->bp;
        u8 port = params->port;
                bnx2x_bmac_enable(params, vars, 0);
                bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000);
        } else {
-               rc = bnx2x_emac_program(params, vars->line_speed,
-                                     vars->duplex);
+               rc = bnx2x_emac_program(params, vars);
 
                bnx2x_emac_enable(params, vars, 0);
 
        msleep(20);
        return rc;
 }
-/* This function should called upon link interrupt */
-/* In case vars->link_up, driver needs to
-       1. Update the pbf
-       2. Disable drain
-       3. Update the shared memory
-       4. Indicate link up
-       5. Set LEDs
-   Otherwise,
-       1. Update shared memory
-       2. Reset BigMac
-       3. Report link down
-       4. Unset LEDs
+/**
+ * The bnx2x_link_update function should be called upon link
+ * interrupt.
+ * Link is considered up as follows:
+ * - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs
+ *   to be up
+ * - SINGLE_MEDIA - The link between the 577xx and the external
+ *   phy (XGXS) need to up as well as the external link of the
+ *   phy (PHY_EXT1)
+ * - DUAL_MEDIA - The link between the 577xx and the first
+ *   external phy needs to be up, and at least one of the 2
+ *   external phy link must be up.
 */
 u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
+       struct link_vars phy_vars[MAX_PHYS];
        u8 port = params->port;
-       u16 gp_status;
-       u8 link_10g;
-       u8 ext_phy_link_up, rc = 0;
-       struct bnx2x_phy *int_phy = ¶ms->phy[INT_PHY];
+       u8 link_10g, phy_index;
+       u8 ext_phy_link_up = 0, cur_link_up, rc = 0;
        u8 is_mi_int = 0;
+       u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
+       u8 active_external_phy = INT_PHY;
+       vars->link_status = 0;
+       for (phy_index = INT_PHY; phy_index < params->num_phys;
+             phy_index++) {
+               phy_vars[phy_index].flow_ctrl = 0;
+               phy_vars[phy_index].link_status = 0;
+               phy_vars[phy_index].line_speed = 0;
+               phy_vars[phy_index].duplex = DUPLEX_FULL;
+               phy_vars[phy_index].phy_link_up = 0;
+               phy_vars[phy_index].link_up = 0;
+       }
 
        DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
                 port, (vars->phy_flags & PHY_XGXS_FLAG),
        /* disable emac */
        REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
 
-       /* Check external link change only for non-direct */
-       ext_phy_link_up = bnx2x_ext_phy_is_link_up(¶ms->phy[EXT_PHY1],
-                                                  params, vars,
-                                                  is_mi_int);
+       /**
+       * Step 1:
+       * Check external link change only for external phys, and apply
+       * priority selection between them in case the link on both phys
+       * is up. Note that the instead of the common vars, a temporary
+       * vars argument is used since each phy may have different link/
+       * speed/duplex result
+       */
+       for (phy_index = EXT_PHY1; phy_index < params->num_phys;
+             phy_index++) {
+               struct bnx2x_phy *phy = ¶ms->phy[phy_index];
+               if (!phy->read_status)
+                       continue;
+               /* Read link status and params of this ext phy */
+               cur_link_up = phy->read_status(phy, params,
+                                              &phy_vars[phy_index]);
+               if (cur_link_up) {
+                       DP(NETIF_MSG_LINK, "phy in index %d link is up\n",
+                                  phy_index);
+               } else {
+                       DP(NETIF_MSG_LINK, "phy in index %d link is down\n",
+                                  phy_index);
+                       continue;
+               }
 
-       /* Read gp_status */
-       CL45_RD_OVER_CL22(bp, int_phy,
-                             MDIO_REG_BANK_GP_STATUS,
-                             MDIO_GP_STATUS_TOP_AN_STATUS1,
-                             &gp_status);
+               if (!ext_phy_link_up) {
+                       ext_phy_link_up = 1;
+                       active_external_phy = phy_index;
+               }
+       }
+       prev_line_speed = vars->line_speed;
+       /**
+       * Step 2:
+       * Read the status of the internal phy. In case of
+       * DIRECT_SINGLE_MEDIA board, this link is the external link,
+       * otherwise this is the link between the 577xx and the first
+       * external phy
+       */
+       if (params->phy[INT_PHY].read_status)
+               params->phy[INT_PHY].read_status(
+                       ¶ms->phy[INT_PHY],
+                       params, vars);
+       /**
+        * The INT_PHY flow control reside in the vars. This include the
+        * case where the speed or flow control are not set to AUTO.
+        * Otherwise, the active external phy flow control result is set
+        * to the vars. The ext_phy_line_speed is needed to check if the
+        * speed is different between the internal phy and external phy.
+        * This case may be result of intermediate link speed change.
+        */
+       if (active_external_phy > INT_PHY) {
+               vars->flow_ctrl = phy_vars[active_external_phy].flow_ctrl;
+               /**
+                * Link speed is taken from the XGXS. AN and FC result from
+                * the external phy.
+                */
+               vars->link_status |= phy_vars[active_external_phy].link_status;
+               ext_phy_line_speed = phy_vars[active_external_phy].line_speed;
+               vars->duplex = phy_vars[active_external_phy].duplex;
+               if (params->phy[active_external_phy].supported &
+                   SUPPORTED_FIBRE)
+                       vars->link_status |= LINK_STATUS_SERDES_LINK;
+               DP(NETIF_MSG_LINK, "Active external phy selected: %x\n",
+                          active_external_phy);
+       }
+       DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x,"
+                  " ext_phy_line_speed = %d\n", vars->flow_ctrl,
+                  vars->link_status, ext_phy_line_speed);
+       /**
+        * Upon link speed change set the NIG into drain mode. Comes to
+        * deals with possible FIFO glitch due to clk change when speed
+        * is decreased without link down indicator
+        */
 
-       rc = bnx2x_link_settings_status(params, vars, gp_status,
-                                     ext_phy_link_up);
-       if (rc != 0)
-               return rc;
+       if (vars->phy_link_up) {
+               if (!(SINGLE_MEDIA_DIRECT(params)) && ext_phy_link_up &&
+                   (ext_phy_line_speed != vars->line_speed)) {
+                       DP(NETIF_MSG_LINK, "Internal link speed %d is"
+                                  " different than the external"
+                                  " link speed %d\n", vars->line_speed,
+                                  ext_phy_line_speed);
+                       vars->phy_link_up = 0;
+               } else if (prev_line_speed != vars->line_speed) {
+                       REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
+                                    + params->port*4, 0);
+                       msleep(1);
+               }
+       }
 
        /* anything 10 and over uses the bmac */
        link_10g = ((vars->line_speed == SPEED_10000) ||
 
        bnx2x_link_int_ack(params, vars, link_10g, is_mi_int);
 
-       /* In case external phy link is up, and internal link is down
-       ( not initialized yet probably after link initialization, it needs
-       to be initialized.
-       Note that after link down-up as result of cable plug,
-       the xgxs link would probably become up again without the need to
-       initialize it*/
-
-       if ((int_phy->type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
-           (int_phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) &&
-           (int_phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) &&
-           (int_phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) &&
-           (int_phy->type && !vars->phy_link_up))
-               bnx2x_init_internal_phy(int_phy, params, vars);
-
-       /* link is up only if both local phy and external phy are up */
-       vars->link_up = (ext_phy_link_up && vars->phy_link_up);
+       /**
+       * In case external phy link is up, and internal link is down
+       * (not initialized yet probably after link initialization, it
+       * needs to be initialized.
+       * Note that after link down-up as result of cable plug, the xgxs
+       * link would probably become up again without the need
+       * initialize it
+       */
+       if (!(SINGLE_MEDIA_DIRECT(params))) {
+               DP(NETIF_MSG_LINK, "ext_phy_link_up = %d, int_link_up = %d,"
+                          " init_preceding = %d\n", ext_phy_link_up,
+                          vars->phy_link_up,
+                          params->phy[EXT_PHY1].flags &
+                          FLAGS_INIT_XGXS_FIRST);
+               if (!(params->phy[EXT_PHY1].flags &
+                     FLAGS_INIT_XGXS_FIRST)
+                   && ext_phy_link_up && !vars->phy_link_up) {
+                       vars->line_speed = ext_phy_line_speed;
+                       if (vars->line_speed < SPEED_1000)
+                               vars->phy_flags |= PHY_SGMII_FLAG;
+                       else
+                               vars->phy_flags &= ~PHY_SGMII_FLAG;
+                       bnx2x_init_internal_phy(¶ms->phy[INT_PHY],
+                                               params,
+                                               vars);
+               }
+       }
+       /**
+        *  Link is up only if both local phy and external phy (in case of
+        *  non-direct board) are up
+        */
+       vars->link_up = (vars->phy_link_up &&
+                        (ext_phy_link_up ||
+                         SINGLE_MEDIA_DIRECT(params)));
 
        if (vars->link_up)
-               rc = bnx2x_update_link_up(params, vars, link_10g, gp_status);
+               rc = bnx2x_update_link_up(params, vars, link_10g);
        else
                rc = bnx2x_update_link_down(params, vars);
 
        return rc;
 }
 
+static void bnx2x_8481_hw_reset(struct bnx2x_phy *phy,
+                               struct link_params *params)
+{
+       bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
+                           MISC_REGISTERS_GPIO_OUTPUT_LOW, 0);
+       bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
+                           MISC_REGISTERS_GPIO_OUTPUT_LOW, 1);
+}
+
+static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy,
+                               struct link_params *params) {
+       u32 swap_val, swap_override;
+       u8 port;
+       /**
+        * The PHY reset is controlled by GPIO 1. Fake the port number
+        * to cancel the swap done in set_gpio()
+        */
+       struct bnx2x *bp = params->bp;
+       swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+       swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
+       port = (swap_val && swap_override) ^ 1;
+       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+                           MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
+}
+
+static void bnx2x_7101_hw_reset(struct bnx2x_phy *phy,
+                               struct link_params *params) {
+       /* Low power mode is controlled by GPIO 2 */
+       bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_2,
+                           MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
+       /* The PHY reset is controlled by GPIO 1 */
+       bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
+                           MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
+}
+/******************************************************************/
+/*                     STATIC PHY DECLARATION                    */
+/******************************************************************/
+
+static struct bnx2x_phy phy_null = {
+       .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
+       .addr           = 0,
+       .flags          = FLAGS_INIT_XGXS_FIRST,
+       .def_md_devad   = 0,
+       .reserved       = 0,
+       .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .mdio_ctrl      = 0,
+       .supported      = 0,
+       .media_type     = ETH_PHY_NOT_PRESENT,
+       .ver_addr       = 0,
+       .req_flow_ctrl  = 0,
+       .req_line_speed = 0,
+       .speed_cap_mask = 0,
+       .req_duplex     = 0,
+       .rsrv           = 0,
+       .config_init    = (config_init_t)NULL,
+       .read_status    = (read_status_t)NULL,
+       .link_reset     = (link_reset_t)NULL,
+       .config_loopback = (config_loopback_t)NULL,
+       .format_fw_ver  = (format_fw_ver_t)NULL,
+       .hw_reset       = (hw_reset_t)NULL,
+       .set_link_led   = (set_link_led_t)NULL
+};
+
+static struct bnx2x_phy phy_serdes = {
+       .type           = PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
+       .addr           = 0xff,
+       .flags          = 0,
+       .def_md_devad   = 0,
+       .reserved       = 0,
+       .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .mdio_ctrl      = 0,
+       .supported      = (SUPPORTED_10baseT_Half |
+                          SUPPORTED_10baseT_Full |
+                          SUPPORTED_100baseT_Half |
+                          SUPPORTED_100baseT_Full |
+                          SUPPORTED_1000baseT_Full |
+                          SUPPORTED_2500baseX_Full |
+                          SUPPORTED_TP |
+                          SUPPORTED_Autoneg |
+                          SUPPORTED_Pause |
+                          SUPPORTED_Asym_Pause),
+       .media_type     = ETH_PHY_UNSPECIFIED,
+       .ver_addr       = 0,
+       .req_flow_ctrl  = 0,
+       .req_line_speed = 0,
+       .speed_cap_mask = 0,
+       .req_duplex     = 0,
+       .rsrv           = 0,
+       .config_init    = (config_init_t)bnx2x_init_serdes,
+       .read_status    = (read_status_t)bnx2x_link_settings_status,
+       .link_reset     = (link_reset_t)bnx2x_int_link_reset,
+       .config_loopback = (config_loopback_t)NULL,
+       .format_fw_ver  = (format_fw_ver_t)NULL,
+       .hw_reset       = (hw_reset_t)NULL,
+       .set_link_led   = (set_link_led_t)NULL
+};
+
+static struct bnx2x_phy phy_xgxs = {
+       .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
+       .addr           = 0xff,
+       .flags          = 0,
+       .def_md_devad   = 0,
+       .reserved       = 0,
+       .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .mdio_ctrl      = 0,
+       .supported      = (SUPPORTED_10baseT_Half |
+                          SUPPORTED_10baseT_Full |
+                          SUPPORTED_100baseT_Half |
+                          SUPPORTED_100baseT_Full |
+                          SUPPORTED_1000baseT_Full |
+                          SUPPORTED_2500baseX_Full |
+                          SUPPORTED_10000baseT_Full |
+                          SUPPORTED_FIBRE |
+                          SUPPORTED_Autoneg |
+                          SUPPORTED_Pause |
+                          SUPPORTED_Asym_Pause),
+       .media_type     = ETH_PHY_UNSPECIFIED,
+       .ver_addr       = 0,
+       .req_flow_ctrl  = 0,
+       .req_line_speed = 0,
+       .speed_cap_mask = 0,
+       .req_duplex     = 0,
+       .rsrv           = 0,
+       .config_init    = (config_init_t)bnx2x_init_xgxs,
+       .read_status    = (read_status_t)bnx2x_link_settings_status,
+       .link_reset     = (link_reset_t)bnx2x_int_link_reset,
+       .config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback,
+       .format_fw_ver  = (format_fw_ver_t)NULL,
+       .hw_reset       = (hw_reset_t)NULL,
+       .set_link_led   = (set_link_led_t)NULL
+};
+
+static struct bnx2x_phy phy_7101 = {
+       .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
+       .addr           = 0xff,
+       .flags          = FLAGS_FAN_FAILURE_DET_REQ,
+       .def_md_devad   = 0,
+       .reserved       = 0,
+       .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .mdio_ctrl      = 0,
+       .supported      = (SUPPORTED_10000baseT_Full |
+                          SUPPORTED_TP |
+                          SUPPORTED_Autoneg |
+                          SUPPORTED_Pause |
+                          SUPPORTED_Asym_Pause),
+       .media_type     = ETH_PHY_BASE_T,
+       .ver_addr       = 0,
+       .req_flow_ctrl  = 0,
+       .req_line_speed = 0,
+       .speed_cap_mask = 0,
+       .req_duplex     = 0,
+       .rsrv           = 0,
+       .config_init    = (config_init_t)bnx2x_7101_config_init,
+       .read_status    = (read_status_t)bnx2x_7101_read_status,
+       .link_reset     = (link_reset_t)bnx2x_common_ext_link_reset,
+       .config_loopback = (config_loopback_t)bnx2x_7101_config_loopback,
+       .format_fw_ver  = (format_fw_ver_t)bnx2x_7101_format_ver,
+       .hw_reset       = (hw_reset_t)bnx2x_7101_hw_reset,
+       .set_link_led   = (set_link_led_t)NULL
+};
+static struct bnx2x_phy phy_8073 = {
+       .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+       .addr           = 0xff,
+       .flags          = FLAGS_HW_LOCK_REQUIRED,
+       .def_md_devad   = 0,
+       .reserved       = 0,
+       .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .mdio_ctrl      = 0,
+       .supported      = (SUPPORTED_10000baseT_Full |
+                          SUPPORTED_2500baseX_Full |
+                          SUPPORTED_1000baseT_Full |
+                          SUPPORTED_FIBRE |
+                          SUPPORTED_Autoneg |
+                          SUPPORTED_Pause |
+                          SUPPORTED_Asym_Pause),
+       .media_type     = ETH_PHY_UNSPECIFIED,
+       .ver_addr       = 0,
+       .req_flow_ctrl  = 0,
+       .req_line_speed = 0,
+       .speed_cap_mask = 0,
+       .req_duplex     = 0,
+       .rsrv           = 0,
+       .config_init    = (config_init_t)bnx2x_8072_8073_config_init,
+       .read_status    = (read_status_t)bnx2x_8073_read_status,
+       .link_reset     = (link_reset_t)bnx2x_8073_link_reset,
+       .config_loopback = (config_loopback_t)NULL,
+       .format_fw_ver  = (format_fw_ver_t)bnx2x_format_ver,
+       .hw_reset       = (hw_reset_t)NULL,
+       .set_link_led   = (set_link_led_t)NULL
+};
+static struct bnx2x_phy phy_8705 = {
+       .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
+       .addr           = 0xff,
+       .flags          = FLAGS_INIT_XGXS_FIRST,
+       .def_md_devad   = 0,
+       .reserved       = 0,
+       .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .mdio_ctrl      = 0,
+       .supported      = (SUPPORTED_10000baseT_Full |
+                          SUPPORTED_FIBRE |
+                          SUPPORTED_Pause |
+                          SUPPORTED_Asym_Pause),
+       .media_type     = ETH_PHY_XFP_FIBER,
+       .ver_addr       = 0,
+       .req_flow_ctrl  = 0,
+       .req_line_speed = 0,
+       .speed_cap_mask = 0,
+       .req_duplex     = 0,
+       .rsrv           = 0,
+       .config_init    = (config_init_t)bnx2x_8705_config_init,
+       .read_status    = (read_status_t)bnx2x_8705_read_status,
+       .link_reset     = (link_reset_t)bnx2x_common_ext_link_reset,
+       .config_loopback = (config_loopback_t)NULL,
+       .format_fw_ver  = (format_fw_ver_t)bnx2x_null_format_ver,
+       .hw_reset       = (hw_reset_t)NULL,
+       .set_link_led   = (set_link_led_t)NULL
+};
+static struct bnx2x_phy phy_8706 = {
+       .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
+       .addr           = 0xff,
+       .flags          = FLAGS_INIT_XGXS_FIRST,
+       .def_md_devad   = 0,
+       .reserved       = 0,
+       .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .mdio_ctrl      = 0,
+       .supported      = (SUPPORTED_10000baseT_Full |
+                          SUPPORTED_1000baseT_Full |
+                          SUPPORTED_FIBRE |
+                          SUPPORTED_Pause |
+                          SUPPORTED_Asym_Pause),
+       .media_type     = ETH_PHY_SFP_FIBER,
+       .ver_addr       = 0,
+       .req_flow_ctrl  = 0,
+       .req_line_speed = 0,
+       .speed_cap_mask = 0,
+       .req_duplex     = 0,
+       .rsrv           = 0,
+       .config_init    = (config_init_t)bnx2x_8706_config_init,
+       .read_status    = (read_status_t)bnx2x_8706_read_status,
+       .link_reset     = (link_reset_t)bnx2x_common_ext_link_reset,
+       .config_loopback = (config_loopback_t)NULL,
+       .format_fw_ver  = (format_fw_ver_t)bnx2x_format_ver,
+       .hw_reset       = (hw_reset_t)NULL,
+       .set_link_led   = (set_link_led_t)NULL
+};
+
+static struct bnx2x_phy phy_8726 = {
+       .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
+       .addr           = 0xff,
+       .flags          = (FLAGS_HW_LOCK_REQUIRED |
+                          FLAGS_INIT_XGXS_FIRST),
+       .def_md_devad   = 0,
+       .reserved       = 0,
+       .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .mdio_ctrl      = 0,
+       .supported      = (SUPPORTED_10000baseT_Full |
+                          SUPPORTED_1000baseT_Full |
+                          SUPPORTED_Autoneg |
+                          SUPPORTED_FIBRE |
+                          SUPPORTED_Pause |
+                          SUPPORTED_Asym_Pause),
+       .media_type     = ETH_PHY_SFP_FIBER,
+       .ver_addr       = 0,
+       .req_flow_ctrl  = 0,
+       .req_line_speed = 0,
+       .speed_cap_mask = 0,
+       .req_duplex     = 0,
+       .rsrv           = 0,
+       .config_init    = (config_init_t)bnx2x_8726_config_init,
+       .read_status    = (read_status_t)bnx2x_8726_read_status,
+       .link_reset     = (link_reset_t)bnx2x_8726_link_reset,
+       .config_loopback = (config_loopback_t)bnx2x_8726_config_loopback,
+       .format_fw_ver  = (format_fw_ver_t)bnx2x_format_ver,
+       .hw_reset       = (hw_reset_t)NULL,
+       .set_link_led   = (set_link_led_t)NULL
+};
+
+static struct bnx2x_phy phy_8727 = {
+       .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+       .addr           = 0xff,
+       .flags          = FLAGS_FAN_FAILURE_DET_REQ,
+       .def_md_devad   = 0,
+       .reserved       = 0,
+       .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .mdio_ctrl      = 0,
+       .supported      = (SUPPORTED_10000baseT_Full |
+                          SUPPORTED_1000baseT_Full |
+                          SUPPORTED_Autoneg |
+                          SUPPORTED_FIBRE |
+                          SUPPORTED_Pause |
+                          SUPPORTED_Asym_Pause),
+       .media_type     = ETH_PHY_SFP_FIBER,
+       .ver_addr       = 0,
+       .req_flow_ctrl  = 0,
+       .req_line_speed = 0,
+       .speed_cap_mask = 0,
+       .req_duplex     = 0,
+       .rsrv           = 0,
+       .config_init    = (config_init_t)bnx2x_8727_config_init,
+       .read_status    = (read_status_t)bnx2x_8727_read_status,
+       .link_reset     = (link_reset_t)bnx2x_8727_link_reset,
+       .config_loopback = (config_loopback_t)NULL,
+       .format_fw_ver  = (format_fw_ver_t)bnx2x_format_ver,
+       .hw_reset       = (hw_reset_t)bnx2x_8727_hw_reset,
+       .set_link_led   = (set_link_led_t)NULL
+};
+static struct bnx2x_phy phy_8481 = {
+       .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+       .addr           = 0xff,
+       .flags          = FLAGS_FAN_FAILURE_DET_REQ,
+       .def_md_devad   = 0,
+       .reserved       = 0,
+       .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .mdio_ctrl      = 0,
+       .supported      = (SUPPORTED_10baseT_Half |
+                          SUPPORTED_10baseT_Full |
+                          SUPPORTED_100baseT_Half |
+                          SUPPORTED_100baseT_Full |
+                          SUPPORTED_1000baseT_Full |
+                          SUPPORTED_10000baseT_Full |
+                          SUPPORTED_TP |
+                          SUPPORTED_Autoneg |
+                          SUPPORTED_Pause |
+                          SUPPORTED_Asym_Pause),
+       .media_type     = ETH_PHY_BASE_T,
+       .ver_addr       = 0,
+       .req_flow_ctrl  = 0,
+       .req_line_speed = 0,
+       .speed_cap_mask = 0,
+       .req_duplex     = 0,
+       .rsrv           = 0,
+       .config_init    = (config_init_t)bnx2x_8481_config_init,
+       .read_status    = (read_status_t)bnx2x_848xx_read_status,
+       .link_reset     = (link_reset_t)bnx2x_8481_link_reset,
+       .config_loopback = (config_loopback_t)NULL,
+       .format_fw_ver  = (format_fw_ver_t)bnx2x_848xx_format_ver,
+       .hw_reset       = (hw_reset_t)bnx2x_8481_hw_reset,
+       .set_link_led   = (set_link_led_t)NULL
+};
+
+static struct bnx2x_phy phy_84823 = {
+       .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
+       .addr           = 0xff,
+       .flags          = FLAGS_FAN_FAILURE_DET_REQ,
+       .def_md_devad   = 0,
+       .reserved       = 0,
+       .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .mdio_ctrl      = 0,
+       .supported      = (SUPPORTED_10baseT_Half |
+                          SUPPORTED_10baseT_Full |
+                          SUPPORTED_100baseT_Half |
+                          SUPPORTED_100baseT_Full |
+                          SUPPORTED_1000baseT_Full |
+                          SUPPORTED_10000baseT_Full |
+                          SUPPORTED_TP |
+                          SUPPORTED_Autoneg |
+                          SUPPORTED_Pause |
+                          SUPPORTED_Asym_Pause),
+       .media_type     = ETH_PHY_BASE_T,
+       .ver_addr       = 0,
+       .req_flow_ctrl  = 0,
+       .req_line_speed = 0,
+       .speed_cap_mask = 0,
+       .req_duplex     = 0,
+       .rsrv           = 0,
+       .config_init    = (config_init_t)bnx2x_848x3_config_init,
+       .read_status    = (read_status_t)bnx2x_848xx_read_status,
+       .link_reset     = (link_reset_t)bnx2x_848x3_link_reset,
+       .config_loopback = (config_loopback_t)NULL,
+       .format_fw_ver  = (format_fw_ver_t)bnx2x_848xx_format_ver,
+       .hw_reset       = (hw_reset_t)NULL,
+       .set_link_led   = (set_link_led_t)NULL
+};
+
+/*****************************************************************/
+/*                                                               */
+/* Populate the phy according. Main function: bnx2x_populate_phy   */
+/*                                                               */
+/*****************************************************************/
+
+static void bnx2x_populate_preemphasis(struct bnx2x *bp, u32 shmem_base,
+                                    struct bnx2x_phy *phy, u8 port,
+                                    u8 phy_index)
+{
+       /* Get the 4 lanes xgxs config rx and tx */
+       u32 rx = 0, tx = 0, i;
+       for (i = 0; i < 2; i++) {
+               /**
+                * INT_PHY and EXT_PHY1 share the same value location in the
+                * shmem. When num_phys is greater than 1, than this value
+                * applies only to EXT_PHY1
+                */
+
+               rx = REG_RD(bp, shmem_base +
+                                 offsetof(struct shmem_region,
+                 dev_info.port_hw_config[port].xgxs_config_rx[i<<1]));
+
+               tx = REG_RD(bp, shmem_base +
+                                 offsetof(struct shmem_region,
+                 dev_info.port_hw_config[port].xgxs_config_tx[i<<1]));
+
+               phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff);
+               phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff);
+
+               phy->tx_preemphasis[i << 1] = ((tx>>16) & 0xffff);
+               phy->tx_preemphasis[(i << 1) + 1] = (tx & 0xffff);
+       }
+}
+
 static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base,
                                    u8 phy_index, u8 port)
 {
 
        return ext_phy_config;
 }
+static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
+                                struct bnx2x_phy *phy)
+{
+       u32 phy_addr;
+       u32 chip_id;
+       u32 switch_cfg = (REG_RD(bp, shmem_base +
+                                      offsetof(struct shmem_region,
+                       dev_info.port_feature_config[port].link_config)) &
+                         PORT_FEATURE_CONNECTED_SWITCH_MASK);
+       chip_id = REG_RD(bp, MISC_REG_CHIP_NUM) << 16;
+       switch (switch_cfg) {
+       case SWITCH_CFG_1G:
+               phy_addr = REG_RD(bp,
+                                       NIG_REG_SERDES0_CTRL_PHY_ADDR +
+                                       port * 0x10);
+               *phy = phy_serdes;
+               break;
+       case SWITCH_CFG_10G:
+               phy_addr = REG_RD(bp,
+                                       NIG_REG_XGXS0_CTRL_PHY_ADDR +
+                                       port * 0x18);
+               *phy = phy_xgxs;
+               break;
+       default:
+               DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
+               return -EINVAL;
+       }
+       phy->addr = (u8)phy_addr;
+       phy->mdio_ctrl = bnx2x_get_emac_base(bp,
+                                           phy->type,
+                                           port);
+       phy->def_md_devad = DEFAULT_PHY_DEV_ADDR;
+
+       DP(NETIF_MSG_LINK, "Internal phy port=%d, addr=0x%x, mdio_ctl=0x%x\n",
+                  port, phy->addr, phy->mdio_ctrl);
+
+       bnx2x_populate_preemphasis(bp, shmem_base, phy, port, INT_PHY);
+       return 0;
+}
 
 static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
                                 u8 phy_index,
                                 u8 port,
                                 struct bnx2x_phy *phy)
 {
-       u32 ext_phy_config;
+       u32 ext_phy_config, phy_type;
 
        ext_phy_config = bnx2x_get_ext_phy_config(bp, shmem_base,
                                                  phy_index, port);
-       phy->type = XGXS_EXT_PHY_TYPE(ext_phy_config);
+       phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
+       /* Select the phy type */
+       switch (phy_type) {
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
+               *phy = phy_8073;
+               break;
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
+               *phy = phy_8705;
+               break;
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
+               *phy = phy_8706;
+               break;
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+               *phy = phy_8726;
+               break;
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
+               /* BCM8727_NOC => BCM8727 no over current */
+               *phy = phy_8727;
+               phy->flags |= FLAGS_NOC;
+               break;
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+               *phy = phy_8727;
+               break;
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
+               *phy = phy_8481;
+               break;
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
+               *phy = phy_84823;
+               break;
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
+               *phy = phy_7101;
+               break;
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
+               *phy = phy_null;
+               return -EINVAL;
+       default:
+               *phy = phy_null;
+               return 0;
+       }
+
        phy->addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
+       bnx2x_populate_preemphasis(bp, shmem_base, phy, port, phy_index);
        phy->mdio_ctrl = bnx2x_get_emac_base(bp, phy->type, port);
        return 0;
 }
                             u8 port, struct bnx2x_phy *phy)
 {
        u8 status = 0;
+       phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
+       if (phy_index == INT_PHY)
+               return bnx2x_populate_int_phy(bp, shmem_base, port, phy);
        status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base,
                                        port, phy);
        return status;
 }
 
+static void bnx2x_phy_def_cfg(struct link_params *params,
+                             struct bnx2x_phy *phy,
+                             u8 actual_phy_idx)
+{
+       struct bnx2x *bp = params->bp;
+       u32 link_config;
+       /* Populate the default phy configuration for MF mode */
+       link_config = REG_RD(bp, params->shmem_base +
+                       offsetof(struct shmem_region, dev_info.
+                       port_feature_config[params->port].link_config));
+       phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
+                               offsetof(struct shmem_region, dev_info.
+                       port_hw_config[params->port].speed_capability_mask));
+
+       phy->req_duplex = DUPLEX_FULL;
+       switch (link_config  & PORT_FEATURE_LINK_SPEED_MASK) {
+       case PORT_FEATURE_LINK_SPEED_10M_HALF:
+               phy->req_duplex = DUPLEX_HALF;
+       case PORT_FEATURE_LINK_SPEED_10M_FULL:
+               phy->req_line_speed = SPEED_10;
+               break;
+       case PORT_FEATURE_LINK_SPEED_100M_HALF:
+               phy->req_duplex = DUPLEX_HALF;
+       case PORT_FEATURE_LINK_SPEED_100M_FULL:
+               phy->req_line_speed = SPEED_100;
+               break;
+       case PORT_FEATURE_LINK_SPEED_1G:
+               phy->req_line_speed = SPEED_1000;
+               break;
+       case PORT_FEATURE_LINK_SPEED_2_5G:
+               phy->req_line_speed = SPEED_2500;
+               break;
+       case PORT_FEATURE_LINK_SPEED_10G_CX4:
+               phy->req_line_speed = SPEED_10000;
+               break;
+       default:
+               phy->req_line_speed = SPEED_AUTO_NEG;
+               break;
+       }
+
+       switch (link_config  & PORT_FEATURE_FLOW_CONTROL_MASK) {
+       case PORT_FEATURE_FLOW_CONTROL_AUTO:
+               phy->req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
+               break;
+       case PORT_FEATURE_FLOW_CONTROL_TX:
+               phy->req_flow_ctrl = BNX2X_FLOW_CTRL_TX;
+               break;
+       case PORT_FEATURE_FLOW_CONTROL_RX:
+               phy->req_flow_ctrl = BNX2X_FLOW_CTRL_RX;
+               break;
+       case PORT_FEATURE_FLOW_CONTROL_BOTH:
+               phy->req_flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
+               break;
+       default:
+               phy->req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+               break;
+       }
+}
+
+u8 bnx2x_phy_probe(struct link_params *params)
+{
+       u8 phy_index, actual_phy_idx, link_cfg_idx;
+
+       struct bnx2x *bp = params->bp;
+       struct bnx2x_phy *phy;
+       params->num_phys = 0;
+       DP(NETIF_MSG_LINK, "Begin phy probe\n");
+
+       for (phy_index = INT_PHY; phy_index < MAX_PHYS;
+             phy_index++) {
+               link_cfg_idx = LINK_CONFIG_IDX(phy_index);
+               actual_phy_idx = phy_index;
+
+               phy = ¶ms->phy[actual_phy_idx];
+               if (bnx2x_populate_phy(bp, phy_index, params->shmem_base,
+                                      params->port,
+                                      phy) != 0) {
+                       params->num_phys = 0;
+                       DP(NETIF_MSG_LINK, "phy probe failed in phy index %d\n",
+                                  phy_index);
+                       for (phy_index = INT_PHY;
+                             phy_index < MAX_PHYS;
+                             phy_index++)
+                               *phy = phy_null;
+                       return -EINVAL;
+               }
+               if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
+                       break;
+
+               bnx2x_phy_def_cfg(params, phy, actual_phy_idx);
+               params->num_phys++;
+       }
+
+       DP(NETIF_MSG_LINK, "End phy probe. #phys found %x\n", params->num_phys);
+       return 0;
+}
+
+u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx)
+{
+       if (phy_idx < params->num_phys)
+               return params->phy[phy_idx].supported;
+       return 0;
+}
+
+
 static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
 {
        struct bnx2x_phy phy[PORT_MAX];