14919Sxy150489 /*
24919Sxy150489 * This file is provided under a CDDLv1 license. When using or
34919Sxy150489 * redistributing this file, you may do so under this license.
44919Sxy150489 * In redistributing this file this license must be included
54919Sxy150489 * and no other modification of this header file is permitted.
64919Sxy150489 *
74919Sxy150489 * CDDL LICENSE SUMMARY
84919Sxy150489 *
98479SChenlu.Chen@Sun.COM * Copyright(c) 1999 - 2009 Intel Corporation. All rights reserved.
104919Sxy150489 *
114919Sxy150489 * The contents of this file are subject to the terms of Version
124919Sxy150489 * 1.0 of the Common Development and Distribution License (the "License").
134919Sxy150489 *
144919Sxy150489 * You should have received a copy of the License with this software.
154919Sxy150489 * You can obtain a copy of the License at
164919Sxy150489 * http://www.opensolaris.org/os/licensing.
174919Sxy150489 * See the License for the specific language governing permissions
184919Sxy150489 * and limitations under the License.
194919Sxy150489 */
204919Sxy150489
214919Sxy150489 /*
228479SChenlu.Chen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
234919Sxy150489 * Use is subject to license terms of the CDDLv1.
244919Sxy150489 */
254919Sxy150489
264919Sxy150489 /*
2711020SMin.Xu@Sun.COM * IntelVersion: 1.86 v3-1-10-1_2009-9-18_Release14-6
284919Sxy150489 */
294919Sxy150489 /*
308479SChenlu.Chen@Sun.COM * 80003ES2LAN Gigabit Ethernet Controller (Copper)
318479SChenlu.Chen@Sun.COM * 80003ES2LAN Gigabit Ethernet Controller (Serdes)
324919Sxy150489 */
334919Sxy150489
344919Sxy150489 #include "e1000_api.h"
354919Sxy150489
364919Sxy150489 static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw);
374919Sxy150489 static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw);
384919Sxy150489 static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw);
394919Sxy150489 static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw);
404919Sxy150489 static void e1000_release_phy_80003es2lan(struct e1000_hw *hw);
414919Sxy150489 static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw);
424919Sxy150489 static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw);
434919Sxy150489 static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
444919Sxy150489 u32 offset, u16 *data);
454919Sxy150489 static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
464919Sxy150489 u32 offset, u16 data);
474919Sxy150489 static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
484919Sxy150489 u16 words, u16 *data);
494919Sxy150489 static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw);
504919Sxy150489 static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw);
514919Sxy150489 static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw);
524919Sxy150489 static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
534919Sxy150489 u16 *duplex);
544919Sxy150489 static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw);
554919Sxy150489 static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw);
564919Sxy150489 static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw);
574919Sxy150489 static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw);
584919Sxy150489 static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
594919Sxy150489 static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex);
604919Sxy150489 static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw);
618479SChenlu.Chen@Sun.COM static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw);
628479SChenlu.Chen@Sun.COM static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
638479SChenlu.Chen@Sun.COM u16 *data);
648479SChenlu.Chen@Sun.COM static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
658479SChenlu.Chen@Sun.COM u16 data);
664919Sxy150489 static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw);
674919Sxy150489 static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw);
684919Sxy150489 static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
696735Scc210113 static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw);
706735Scc210113 static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw);
714919Sxy150489
724919Sxy150489 /*
734919Sxy150489 * A table for the GG82563 cable length where the range is defined with a
744919Sxy150489 * lower bound at "index" and the upper bound at "index + 5".
754919Sxy150489 */
764919Sxy150489 static const u16 e1000_gg82563_cable_length_table[] =
774919Sxy150489 {0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF};
784919Sxy150489
794919Sxy150489 #define GG82563_CABLE_LENGTH_TABLE_SIZE \
804919Sxy150489 (sizeof (e1000_gg82563_cable_length_table) / \
814919Sxy150489 sizeof (e1000_gg82563_cable_length_table[0]))
824919Sxy150489
834919Sxy150489 /*
844919Sxy150489 * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs.
854919Sxy150489 * @hw: pointer to the HW structure
864919Sxy150489 */
874919Sxy150489 static s32
e1000_init_phy_params_80003es2lan(struct e1000_hw * hw)884919Sxy150489 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
894919Sxy150489 {
904919Sxy150489 struct e1000_phy_info *phy = &hw->phy;
914919Sxy150489 s32 ret_val = E1000_SUCCESS;
924919Sxy150489
934919Sxy150489 DEBUGFUNC("e1000_init_phy_params_80003es2lan");
944919Sxy150489
956735Scc210113 if (hw->phy.media_type != e1000_media_type_copper) {
964919Sxy150489 phy->type = e1000_phy_none;
974919Sxy150489 goto out;
986735Scc210113 } else {
996735Scc210113 phy->ops.power_up = e1000_power_up_phy_copper;
1006735Scc210113 phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan;
1014919Sxy150489 }
1024919Sxy150489
1034919Sxy150489 phy->addr = 1;
1044919Sxy150489 phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
1054919Sxy150489 phy->reset_delay_us = 100;
1064919Sxy150489 phy->type = e1000_phy_gg82563;
1074919Sxy150489
1086735Scc210113 phy->ops.acquire = e1000_acquire_phy_80003es2lan;
1096735Scc210113 phy->ops.check_polarity = e1000_check_polarity_m88;
1106735Scc210113 phy->ops.check_reset_block = e1000_check_reset_block_generic;
1116735Scc210113 phy->ops.commit = e1000_phy_sw_reset_generic;
1126735Scc210113 phy->ops.get_cfg_done = e1000_get_cfg_done_80003es2lan;
1136735Scc210113 phy->ops.get_info = e1000_get_phy_info_m88;
1146735Scc210113 phy->ops.release = e1000_release_phy_80003es2lan;
1156735Scc210113 phy->ops.reset = e1000_phy_hw_reset_generic;
1166735Scc210113 phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
1174919Sxy150489
1186735Scc210113 phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan;
1196735Scc210113 phy->ops.get_cable_length = e1000_get_cable_length_80003es2lan;
1206735Scc210113 phy->ops.read_reg = e1000_read_phy_reg_gg82563_80003es2lan;
1216735Scc210113 phy->ops.write_reg = e1000_write_phy_reg_gg82563_80003es2lan;
1224919Sxy150489
1238479SChenlu.Chen@Sun.COM phy->ops.cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan;
1248479SChenlu.Chen@Sun.COM
1254919Sxy150489 /* This can only be done after all function pointers are setup. */
1264919Sxy150489 ret_val = e1000_get_phy_id(hw);
1274919Sxy150489
1284919Sxy150489 /* Verify phy id */
1294919Sxy150489 if (phy->id != GG82563_E_PHY_ID) {
1304919Sxy150489 ret_val = -E1000_ERR_PHY;
1314919Sxy150489 goto out;
1324919Sxy150489 }
1334919Sxy150489
1344919Sxy150489 out:
1354919Sxy150489 return (ret_val);
1364919Sxy150489 }
1374919Sxy150489
1384919Sxy150489 /*
1394919Sxy150489 * e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs.
1404919Sxy150489 * @hw: pointer to the HW structure
1414919Sxy150489 */
1424919Sxy150489 static s32
e1000_init_nvm_params_80003es2lan(struct e1000_hw * hw)1434919Sxy150489 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
1444919Sxy150489 {
1454919Sxy150489 struct e1000_nvm_info *nvm = &hw->nvm;
1464919Sxy150489 u32 eecd = E1000_READ_REG(hw, E1000_EECD);
1474919Sxy150489 u16 size;
1484919Sxy150489
1494919Sxy150489 DEBUGFUNC("e1000_init_nvm_params_80003es2lan");
1504919Sxy150489
1514919Sxy150489 nvm->opcode_bits = 8;
1524919Sxy150489 nvm->delay_usec = 1;
1534919Sxy150489 switch (nvm->override) {
1544919Sxy150489 case e1000_nvm_override_spi_large:
1554919Sxy150489 nvm->page_size = 32;
1564919Sxy150489 nvm->address_bits = 16;
1574919Sxy150489 break;
1584919Sxy150489 case e1000_nvm_override_spi_small:
1594919Sxy150489 nvm->page_size = 8;
1604919Sxy150489 nvm->address_bits = 8;
1614919Sxy150489 break;
1624919Sxy150489 default:
1634919Sxy150489 nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
1644919Sxy150489 nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
1654919Sxy150489 break;
1664919Sxy150489 }
1674919Sxy150489
1684919Sxy150489 nvm->type = e1000_nvm_eeprom_spi;
1694919Sxy150489
1704919Sxy150489 size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
1714919Sxy150489 E1000_EECD_SIZE_EX_SHIFT);
1724919Sxy150489
1734919Sxy150489 /*
1744919Sxy150489 * Added to a constant, "size" becomes the left-shift value
1754919Sxy150489 * for setting word_size.
1764919Sxy150489 */
1774919Sxy150489 size += NVM_WORD_SIZE_BASE_SHIFT;
17810680SMin.Xu@Sun.COM
1796735Scc210113 /* EEPROM access above 16k is unsupported */
1806735Scc210113 if (size > 14)
1816735Scc210113 size = 14;
1824919Sxy150489 nvm->word_size = 1 << size;
1834919Sxy150489
1844919Sxy150489 /* Function Pointers */
1856735Scc210113 nvm->ops.acquire = e1000_acquire_nvm_80003es2lan;
1866735Scc210113 nvm->ops.read = e1000_read_nvm_eerd;
1876735Scc210113 nvm->ops.release = e1000_release_nvm_80003es2lan;
1886735Scc210113 nvm->ops.update = e1000_update_nvm_checksum_generic;
1896735Scc210113 nvm->ops.valid_led_default = e1000_valid_led_default_generic;
1906735Scc210113 nvm->ops.validate = e1000_validate_nvm_checksum_generic;
1916735Scc210113 nvm->ops.write = e1000_write_nvm_80003es2lan;
1924919Sxy150489
1934919Sxy150489 return (E1000_SUCCESS);
1944919Sxy150489 }
1954919Sxy150489
1964919Sxy150489 /*
1974919Sxy150489 * e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs.
1984919Sxy150489 * @hw: pointer to the HW structure
1994919Sxy150489 */
2004919Sxy150489 static s32
e1000_init_mac_params_80003es2lan(struct e1000_hw * hw)2014919Sxy150489 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw)
2024919Sxy150489 {
2034919Sxy150489 struct e1000_mac_info *mac = &hw->mac;
2044919Sxy150489 s32 ret_val = E1000_SUCCESS;
2054919Sxy150489
2064919Sxy150489 DEBUGFUNC("e1000_init_mac_params_80003es2lan");
2074919Sxy150489
2084919Sxy150489 /* Set media type */
2094919Sxy150489 switch (hw->device_id) {
2104919Sxy150489 case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
2116735Scc210113 hw->phy.media_type = e1000_media_type_internal_serdes;
2124919Sxy150489 break;
2134919Sxy150489 default:
2146735Scc210113 hw->phy.media_type = e1000_media_type_copper;
2154919Sxy150489 break;
2164919Sxy150489 }
2174919Sxy150489
2184919Sxy150489 /* Set mta register count */
2194919Sxy150489 mac->mta_reg_count = 128;
2204919Sxy150489 /* Set rar entry count */
2214919Sxy150489 mac->rar_entry_count = E1000_RAR_ENTRIES;
2224919Sxy150489 /* Set if part includes ASF firmware */
2237607STed.You@Sun.COM mac->asf_firmware_present = true;
2244919Sxy150489 /* Set if manageability features are enabled. */
2254919Sxy150489 mac->arc_subsystem_valid =
2264919Sxy150489 (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK)
2277607STed.You@Sun.COM ? true : false;
2284919Sxy150489
2294919Sxy150489 /* Function pointers */
2304919Sxy150489
2314919Sxy150489 /* bus type/speed/width */
2326735Scc210113 mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
2334919Sxy150489 /* reset */
2346735Scc210113 mac->ops.reset_hw = e1000_reset_hw_80003es2lan;
2354919Sxy150489 /* hw initialization */
2366735Scc210113 mac->ops.init_hw = e1000_init_hw_80003es2lan;
2374919Sxy150489 /* link setup */
2386735Scc210113 mac->ops.setup_link = e1000_setup_link_generic;
2394919Sxy150489 /* physical interface link setup */
2406735Scc210113 mac->ops.setup_physical_interface =
2416735Scc210113 (hw->phy.media_type == e1000_media_type_copper)
2424919Sxy150489 ? e1000_setup_copper_link_80003es2lan
2434919Sxy150489 : e1000_setup_fiber_serdes_link_generic;
2444919Sxy150489 /* check for link */
2456735Scc210113 switch (hw->phy.media_type) {
2464919Sxy150489 case e1000_media_type_copper:
2476735Scc210113 mac->ops.check_for_link = e1000_check_for_copper_link_generic;
2484919Sxy150489 break;
2494919Sxy150489 case e1000_media_type_fiber:
2506735Scc210113 mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
2514919Sxy150489 break;
2524919Sxy150489 case e1000_media_type_internal_serdes:
2536735Scc210113 mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
2544919Sxy150489 break;
2554919Sxy150489 default:
2564919Sxy150489 ret_val = -E1000_ERR_CONFIG;
2574919Sxy150489 goto out;
2584919Sxy150489 }
2594919Sxy150489 /* check management mode */
2606735Scc210113 mac->ops.check_mng_mode = e1000_check_mng_mode_generic;
2614919Sxy150489 /* multicast address update */
2626735Scc210113 mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
2634919Sxy150489 /* writing VFTA */
2646735Scc210113 mac->ops.write_vfta = e1000_write_vfta_generic;
2654919Sxy150489 /* clearing VFTA */
2666735Scc210113 mac->ops.clear_vfta = e1000_clear_vfta_generic;
2674919Sxy150489 /* setting MTA */
2686735Scc210113 mac->ops.mta_set = e1000_mta_set_generic;
2696735Scc210113 /* read mac address */
2706735Scc210113 mac->ops.read_mac_addr = e1000_read_mac_addr_80003es2lan;
27110680SMin.Xu@Sun.COM /* ID LED init */
27210680SMin.Xu@Sun.COM mac->ops.id_led_init = e1000_id_led_init_generic;
2734919Sxy150489 /* blink LED */
2746735Scc210113 mac->ops.blink_led = e1000_blink_led_generic;
2754919Sxy150489 /* setup LED */
2766735Scc210113 mac->ops.setup_led = e1000_setup_led_generic;
2774919Sxy150489 /* cleanup LED */
2786735Scc210113 mac->ops.cleanup_led = e1000_cleanup_led_generic;
2794919Sxy150489 /* turn on/off LED */
2806735Scc210113 mac->ops.led_on = e1000_led_on_generic;
2816735Scc210113 mac->ops.led_off = e1000_led_off_generic;
2824919Sxy150489 /* clear hardware counters */
2836735Scc210113 mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan;
2844919Sxy150489 /* link info */
2856735Scc210113 mac->ops.get_link_up_info = e1000_get_link_up_info_80003es2lan;
2864919Sxy150489
28710680SMin.Xu@Sun.COM /* set lan id for port to determine which phy lock to use */
28810680SMin.Xu@Sun.COM hw->mac.ops.set_lan_id(hw);
2894919Sxy150489 out:
2904919Sxy150489 return (ret_val);
2914919Sxy150489 }
2924919Sxy150489
2934919Sxy150489 /*
2944919Sxy150489 * e1000_init_function_pointers_80003es2lan - Init ESB2 func ptrs.
2954919Sxy150489 * @hw: pointer to the HW structure
2964919Sxy150489 *
2978479SChenlu.Chen@Sun.COM * Called to initialize all function pointers and parameters.
2984919Sxy150489 */
2994919Sxy150489 void
e1000_init_function_pointers_80003es2lan(struct e1000_hw * hw)3004919Sxy150489 e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw)
3014919Sxy150489 {
3024919Sxy150489 DEBUGFUNC("e1000_init_function_pointers_80003es2lan");
3034919Sxy150489
3046735Scc210113 hw->mac.ops.init_params = e1000_init_mac_params_80003es2lan;
3056735Scc210113 hw->nvm.ops.init_params = e1000_init_nvm_params_80003es2lan;
3066735Scc210113 hw->phy.ops.init_params = e1000_init_phy_params_80003es2lan;
3074919Sxy150489 }
3084919Sxy150489
3094919Sxy150489 /*
3104919Sxy150489 * e1000_acquire_phy_80003es2lan - Acquire rights to access PHY
3114919Sxy150489 * @hw: pointer to the HW structure
3124919Sxy150489 *
3138479SChenlu.Chen@Sun.COM * A wrapper to acquire access rights to the correct PHY.
3144919Sxy150489 */
3154919Sxy150489 static s32
e1000_acquire_phy_80003es2lan(struct e1000_hw * hw)3164919Sxy150489 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
3174919Sxy150489 {
3184919Sxy150489 u16 mask;
3194919Sxy150489
3204919Sxy150489 DEBUGFUNC("e1000_acquire_phy_80003es2lan");
3214919Sxy150489
3224919Sxy150489 mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
3234919Sxy150489
3244919Sxy150489 return (e1000_acquire_swfw_sync_80003es2lan(hw, mask));
3254919Sxy150489 }
3264919Sxy150489
3274919Sxy150489 /*
3284919Sxy150489 * e1000_release_phy_80003es2lan - Release rights to access PHY
3294919Sxy150489 * @hw: pointer to the HW structure
3304919Sxy150489 *
3318479SChenlu.Chen@Sun.COM * A wrapper to release access rights to the correct PHY.
3324919Sxy150489 */
3334919Sxy150489 static void
e1000_release_phy_80003es2lan(struct e1000_hw * hw)3344919Sxy150489 e1000_release_phy_80003es2lan(struct e1000_hw *hw)
3354919Sxy150489 {
3364919Sxy150489 u16 mask;
3374919Sxy150489
3384919Sxy150489 DEBUGFUNC("e1000_release_phy_80003es2lan");
3394919Sxy150489
3404919Sxy150489 mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
3418479SChenlu.Chen@Sun.COM e1000_release_swfw_sync_80003es2lan(hw, mask);
3428479SChenlu.Chen@Sun.COM }
3438479SChenlu.Chen@Sun.COM
3448479SChenlu.Chen@Sun.COM /*
3458479SChenlu.Chen@Sun.COM * e1000_acquire_mac_csr_80003es2lan - Acquire rights to access Kumeran register
3468479SChenlu.Chen@Sun.COM * @hw: pointer to the HW structure
3478479SChenlu.Chen@Sun.COM *
3488479SChenlu.Chen@Sun.COM * Acquire the semaphore to access the Kumeran interface.
3498479SChenlu.Chen@Sun.COM *
3508479SChenlu.Chen@Sun.COM */
3518479SChenlu.Chen@Sun.COM static s32
e1000_acquire_mac_csr_80003es2lan(struct e1000_hw * hw)3528479SChenlu.Chen@Sun.COM e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw)
3538479SChenlu.Chen@Sun.COM {
3548479SChenlu.Chen@Sun.COM u16 mask;
3558479SChenlu.Chen@Sun.COM
3568479SChenlu.Chen@Sun.COM DEBUGFUNC("e1000_acquire_mac_csr_80003es2lan");
3578479SChenlu.Chen@Sun.COM
3588479SChenlu.Chen@Sun.COM mask = E1000_SWFW_CSR_SM;
3598479SChenlu.Chen@Sun.COM
3608479SChenlu.Chen@Sun.COM return (e1000_acquire_swfw_sync_80003es2lan(hw, mask));
3618479SChenlu.Chen@Sun.COM }
3628479SChenlu.Chen@Sun.COM
3638479SChenlu.Chen@Sun.COM /*
3648479SChenlu.Chen@Sun.COM * e1000_release_mac_csr_80003es2lan - Release rights to access Kumeran Register
3658479SChenlu.Chen@Sun.COM * @hw: pointer to the HW structure
3668479SChenlu.Chen@Sun.COM *
3678479SChenlu.Chen@Sun.COM * Release the semaphore used to access the Kumeran interface
3688479SChenlu.Chen@Sun.COM */
3698479SChenlu.Chen@Sun.COM static void
e1000_release_mac_csr_80003es2lan(struct e1000_hw * hw)3708479SChenlu.Chen@Sun.COM e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw)
3718479SChenlu.Chen@Sun.COM {
3728479SChenlu.Chen@Sun.COM u16 mask;
3738479SChenlu.Chen@Sun.COM
3748479SChenlu.Chen@Sun.COM DEBUGFUNC("e1000_release_mac_csr_80003es2lan");
3758479SChenlu.Chen@Sun.COM
3768479SChenlu.Chen@Sun.COM mask = E1000_SWFW_CSR_SM;
3776735Scc210113
3784919Sxy150489 e1000_release_swfw_sync_80003es2lan(hw, mask);
3794919Sxy150489 }
3804919Sxy150489
3814919Sxy150489 /*
3824919Sxy150489 * e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM
3834919Sxy150489 * @hw: pointer to the HW structure
3844919Sxy150489 *
3858479SChenlu.Chen@Sun.COM * Acquire the semaphore to access the EEPROM.
3864919Sxy150489 */
3874919Sxy150489 static s32
e1000_acquire_nvm_80003es2lan(struct e1000_hw * hw)3884919Sxy150489 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw)
3894919Sxy150489 {
3904919Sxy150489 s32 ret_val;
3914919Sxy150489
3924919Sxy150489 DEBUGFUNC("e1000_acquire_nvm_80003es2lan");
3934919Sxy150489
3944919Sxy150489 ret_val = e1000_acquire_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
3954919Sxy150489 if (ret_val)
3964919Sxy150489 goto out;
3974919Sxy150489
3984919Sxy150489 ret_val = e1000_acquire_nvm_generic(hw);
3994919Sxy150489
4004919Sxy150489 if (ret_val)
4014919Sxy150489 e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
4024919Sxy150489
4034919Sxy150489 out:
4044919Sxy150489 return (ret_val);
4054919Sxy150489 }
4064919Sxy150489
4074919Sxy150489 /*
4084919Sxy150489 * e1000_release_nvm_80003es2lan - Relinquish rights to access NVM
4094919Sxy150489 * @hw: pointer to the HW structure
4104919Sxy150489 *
4118479SChenlu.Chen@Sun.COM * Release the semaphore used to access the EEPROM.
4124919Sxy150489 */
4134919Sxy150489 static void
e1000_release_nvm_80003es2lan(struct e1000_hw * hw)4144919Sxy150489 e1000_release_nvm_80003es2lan(struct e1000_hw *hw)
4154919Sxy150489 {
4164919Sxy150489 DEBUGFUNC("e1000_release_nvm_80003es2lan");
4174919Sxy150489
4184919Sxy150489 e1000_release_nvm_generic(hw);
4194919Sxy150489 e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
4204919Sxy150489 }
4214919Sxy150489
4224919Sxy150489 /*
4234919Sxy150489 * e1000_acquire_swfw_sync_80003es2lan - Acquire SW/FW semaphore
4244919Sxy150489 * @hw: pointer to the HW structure
4254919Sxy150489 * @mask: specifies which semaphore to acquire
4264919Sxy150489 *
4274919Sxy150489 * Acquire the SW/FW semaphore to access the PHY or NVM. The mask
4284919Sxy150489 * will also specify which port we're acquiring the lock for.
4294919Sxy150489 */
4304919Sxy150489 static s32
e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw * hw,u16 mask)4314919Sxy150489 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
4324919Sxy150489 {
4334919Sxy150489 u32 swfw_sync;
4344919Sxy150489 u32 swmask = mask;
4354919Sxy150489 u32 fwmask = mask << 16;
4364919Sxy150489 s32 ret_val = E1000_SUCCESS;
4378479SChenlu.Chen@Sun.COM s32 i = 0, timeout = 50;
4384919Sxy150489
4394919Sxy150489 DEBUGFUNC("e1000_acquire_swfw_sync_80003es2lan");
4404919Sxy150489
4414919Sxy150489 while (i < timeout) {
4424919Sxy150489 if (e1000_get_hw_semaphore_generic(hw)) {
4434919Sxy150489 ret_val = -E1000_ERR_SWFW_SYNC;
4444919Sxy150489 goto out;
4454919Sxy150489 }
4464919Sxy150489
4474919Sxy150489 swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
4484919Sxy150489 if (!(swfw_sync & (fwmask | swmask)))
4494919Sxy150489 break;
4504919Sxy150489
4514919Sxy150489 /*
4524919Sxy150489 * Firmware currently using resource (fwmask)
4534919Sxy150489 * or other software thread using resource (swmask)
4544919Sxy150489 */
4554919Sxy150489 e1000_put_hw_semaphore_generic(hw);
4564919Sxy150489 msec_delay_irq(5);
4574919Sxy150489 i++;
4584919Sxy150489 }
4594919Sxy150489
4604919Sxy150489 if (i == timeout) {
4614919Sxy150489 DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
4624919Sxy150489 ret_val = -E1000_ERR_SWFW_SYNC;
4634919Sxy150489 goto out;
4644919Sxy150489 }
4654919Sxy150489
4664919Sxy150489 swfw_sync |= swmask;
4674919Sxy150489 E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
4684919Sxy150489
4694919Sxy150489 e1000_put_hw_semaphore_generic(hw);
4704919Sxy150489
4714919Sxy150489 out:
4724919Sxy150489 return (ret_val);
4734919Sxy150489 }
4744919Sxy150489
4754919Sxy150489 /*
4764919Sxy150489 * e1000_release_swfw_sync_80003es2lan - Release SW/FW semaphore
4774919Sxy150489 * @hw: pointer to the HW structure
4784919Sxy150489 * @mask: specifies which semaphore to acquire
4794919Sxy150489 *
4804919Sxy150489 * Release the SW/FW semaphore used to access the PHY or NVM. The mask
4814919Sxy150489 * will also specify which port we're releasing the lock for.
4824919Sxy150489 */
4834919Sxy150489 static void
e1000_release_swfw_sync_80003es2lan(struct e1000_hw * hw,u16 mask)4844919Sxy150489 e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
4854919Sxy150489 {
4864919Sxy150489 u32 swfw_sync;
4874919Sxy150489
4884919Sxy150489 DEBUGFUNC("e1000_release_swfw_sync_80003es2lan");
4894919Sxy150489
4904919Sxy150489 while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS) {
4914919Sxy150489 /* Empty */
4924919Sxy150489 }
4934919Sxy150489
4944919Sxy150489 swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
4954919Sxy150489 swfw_sync &= ~mask;
4964919Sxy150489 E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
4974919Sxy150489
4984919Sxy150489 e1000_put_hw_semaphore_generic(hw);
4994919Sxy150489 }
5004919Sxy150489
5014919Sxy150489 /*
5024919Sxy150489 * e1000_read_phy_reg_gg82563_80003es2lan - Read GG82563 PHY register
5034919Sxy150489 * @hw: pointer to the HW structure
5044919Sxy150489 * @offset: offset of the register to read
5054919Sxy150489 * @data: pointer to the data returned from the operation
5064919Sxy150489 *
5078479SChenlu.Chen@Sun.COM * Read the GG82563 PHY register.
5084919Sxy150489 */
5094919Sxy150489 static s32
e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw * hw,u32 offset,u16 * data)5104919Sxy150489 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
5114919Sxy150489 u32 offset, u16 *data)
5124919Sxy150489 {
5134919Sxy150489 s32 ret_val;
5144919Sxy150489 u32 page_select;
5154919Sxy150489 u16 temp;
5164919Sxy150489
5174919Sxy150489 DEBUGFUNC("e1000_read_phy_reg_gg82563_80003es2lan");
5184919Sxy150489
5196735Scc210113 ret_val = e1000_acquire_phy_80003es2lan(hw);
5206735Scc210113 if (ret_val)
5216735Scc210113 goto out;
5226735Scc210113
5234919Sxy150489 /* Select Configuration Page */
5244919Sxy150489 if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
5254919Sxy150489 page_select = GG82563_PHY_PAGE_SELECT;
5264919Sxy150489 } else {
5274919Sxy150489 /*
5284919Sxy150489 * Use Alternative Page Select register to access
5294919Sxy150489 * registers 30 and 31
5304919Sxy150489 */
5314919Sxy150489 page_select = GG82563_PHY_PAGE_SELECT_ALT;
5324919Sxy150489 }
5334919Sxy150489
5344919Sxy150489 temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
5356735Scc210113 ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp);
5366735Scc210113 if (ret_val) {
5376735Scc210113 e1000_release_phy_80003es2lan(hw);
5384919Sxy150489 goto out;
5396735Scc210113 }
5404919Sxy150489
54110680SMin.Xu@Sun.COM if (hw->dev_spec._80003es2lan.mdic_wa_enable == true) {
54210680SMin.Xu@Sun.COM /*
54310680SMin.Xu@Sun.COM * The "ready" bit in the MDIC register may be incorrectly set
54410680SMin.Xu@Sun.COM * before the device has completed the "Page Select" MDI
54510680SMin.Xu@Sun.COM * transaction. So we wait 200us after each MDI command...
54610680SMin.Xu@Sun.COM */
54710680SMin.Xu@Sun.COM usec_delay(200);
5484919Sxy150489
54910680SMin.Xu@Sun.COM /* ...and verify the command was successful. */
55010680SMin.Xu@Sun.COM ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp);
5514919Sxy150489
55210680SMin.Xu@Sun.COM if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
55310680SMin.Xu@Sun.COM ret_val = -E1000_ERR_PHY;
55410680SMin.Xu@Sun.COM e1000_release_phy_80003es2lan(hw);
55510680SMin.Xu@Sun.COM goto out;
55610680SMin.Xu@Sun.COM }
55710680SMin.Xu@Sun.COM
55810680SMin.Xu@Sun.COM usec_delay(200);
5594919Sxy150489
56010680SMin.Xu@Sun.COM ret_val = e1000_read_phy_reg_mdic(hw,
56110680SMin.Xu@Sun.COM MAX_PHY_REG_ADDRESS & offset,
56210680SMin.Xu@Sun.COM data);
5634919Sxy150489
56410680SMin.Xu@Sun.COM usec_delay(200);
56510680SMin.Xu@Sun.COM } else
56610680SMin.Xu@Sun.COM ret_val = e1000_read_phy_reg_mdic(hw,
56710680SMin.Xu@Sun.COM MAX_PHY_REG_ADDRESS & offset,
56810680SMin.Xu@Sun.COM data);
5694919Sxy150489
5706735Scc210113 e1000_release_phy_80003es2lan(hw);
5714919Sxy150489
5724919Sxy150489 out:
5734919Sxy150489 return (ret_val);
5744919Sxy150489 }
5754919Sxy150489
5764919Sxy150489 /*
5774919Sxy150489 * e1000_write_phy_reg_gg82563_80003es2lan - Write GG82563 PHY register
5784919Sxy150489 * @hw: pointer to the HW structure
5794919Sxy150489 * @offset: offset of the register to read
5804919Sxy150489 * @data: value to write to the register
5814919Sxy150489 *
5828479SChenlu.Chen@Sun.COM * Write to the GG82563 PHY register.
5834919Sxy150489 */
5844919Sxy150489 static s32
e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw * hw,u32 offset,u16 data)5854919Sxy150489 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
5864919Sxy150489 u32 offset, u16 data)
5874919Sxy150489 {
5884919Sxy150489 s32 ret_val;
5894919Sxy150489 u32 page_select;
5904919Sxy150489 u16 temp;
5914919Sxy150489
5924919Sxy150489 DEBUGFUNC("e1000_write_phy_reg_gg82563_80003es2lan");
5934919Sxy150489
5946735Scc210113 ret_val = e1000_acquire_phy_80003es2lan(hw);
5956735Scc210113 if (ret_val)
5966735Scc210113 goto out;
5976735Scc210113
5984919Sxy150489 /* Select Configuration Page */
5994919Sxy150489 if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
6004919Sxy150489 page_select = GG82563_PHY_PAGE_SELECT;
6014919Sxy150489 } else {
6024919Sxy150489 /*
6034919Sxy150489 * Use Alternative Page Select register to access
6044919Sxy150489 * registers 30 and 31
6054919Sxy150489 */
6064919Sxy150489 page_select = GG82563_PHY_PAGE_SELECT_ALT;
6074919Sxy150489 }
6084919Sxy150489
6094919Sxy150489 temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
6106735Scc210113 ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp);
6116735Scc210113 if (ret_val) {
6126735Scc210113 e1000_release_phy_80003es2lan(hw);
6134919Sxy150489 goto out;
6146735Scc210113 }
6154919Sxy150489
61610680SMin.Xu@Sun.COM if (hw->dev_spec._80003es2lan.mdic_wa_enable == true) {
61710680SMin.Xu@Sun.COM /*
61810680SMin.Xu@Sun.COM * The "ready" bit in the MDIC register may be incorrectly set
61910680SMin.Xu@Sun.COM * before the device has completed the "Page Select" MDI
62010680SMin.Xu@Sun.COM * transaction. So we wait 200us after each MDI command...
62110680SMin.Xu@Sun.COM */
62210680SMin.Xu@Sun.COM usec_delay(200);
6234919Sxy150489
62410680SMin.Xu@Sun.COM /* ...and verify the command was successful. */
62510680SMin.Xu@Sun.COM ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp);
6264919Sxy150489
62710680SMin.Xu@Sun.COM if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
62810680SMin.Xu@Sun.COM ret_val = -E1000_ERR_PHY;
62910680SMin.Xu@Sun.COM e1000_release_phy_80003es2lan(hw);
63010680SMin.Xu@Sun.COM goto out;
63110680SMin.Xu@Sun.COM }
63210680SMin.Xu@Sun.COM
63310680SMin.Xu@Sun.COM usec_delay(200);
6344919Sxy150489
63510680SMin.Xu@Sun.COM ret_val = e1000_write_phy_reg_mdic(hw,
63610680SMin.Xu@Sun.COM MAX_PHY_REG_ADDRESS & offset,
63710680SMin.Xu@Sun.COM data);
6384919Sxy150489
63910680SMin.Xu@Sun.COM usec_delay(200);
64010680SMin.Xu@Sun.COM } else
64110680SMin.Xu@Sun.COM ret_val = e1000_write_phy_reg_mdic(hw,
64210680SMin.Xu@Sun.COM MAX_PHY_REG_ADDRESS & offset,
64310680SMin.Xu@Sun.COM data);
6444919Sxy150489
6456735Scc210113 e1000_release_phy_80003es2lan(hw);
6464919Sxy150489
6474919Sxy150489 out:
6484919Sxy150489 return (ret_val);
6494919Sxy150489 }
6504919Sxy150489
6514919Sxy150489 /*
6524919Sxy150489 * e1000_write_nvm_80003es2lan - Write to ESB2 NVM
6534919Sxy150489 * @hw: pointer to the HW structure
6544919Sxy150489 * @offset: offset of the register to read
6554919Sxy150489 * @words: number of words to write
6564919Sxy150489 * @data: buffer of data to write to the NVM
6574919Sxy150489 *
6588479SChenlu.Chen@Sun.COM * Write "words" of data to the ESB2 NVM.
6594919Sxy150489 */
6604919Sxy150489 static s32
e1000_write_nvm_80003es2lan(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)6614919Sxy150489 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
6624919Sxy150489 u16 words, u16 *data)
6634919Sxy150489 {
6644919Sxy150489 DEBUGFUNC("e1000_write_nvm_80003es2lan");
6654919Sxy150489
6664919Sxy150489 return (e1000_write_nvm_spi(hw, offset, words, data));
6674919Sxy150489 }
6684919Sxy150489
6694919Sxy150489 /*
6704919Sxy150489 * e1000_get_cfg_done_80003es2lan - Wait for configuration to complete
6714919Sxy150489 * @hw: pointer to the HW structure
6724919Sxy150489 *
6734919Sxy150489 * Wait a specific amount of time for manageability processes to complete.
6744919Sxy150489 * This is a function pointer entry point called by the phy module.
6754919Sxy150489 */
6764919Sxy150489 static s32
e1000_get_cfg_done_80003es2lan(struct e1000_hw * hw)6774919Sxy150489 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw)
6784919Sxy150489 {
6794919Sxy150489 s32 timeout = PHY_CFG_TIMEOUT;
6804919Sxy150489 s32 ret_val = E1000_SUCCESS;
6814919Sxy150489 u32 mask = E1000_NVM_CFG_DONE_PORT_0;
6824919Sxy150489
6834919Sxy150489 DEBUGFUNC("e1000_get_cfg_done_80003es2lan");
6844919Sxy150489
6854919Sxy150489 if (hw->bus.func == 1)
6864919Sxy150489 mask = E1000_NVM_CFG_DONE_PORT_1;
6874919Sxy150489
6884919Sxy150489 while (timeout) {
6894919Sxy150489 if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask)
6904919Sxy150489 break;
6914919Sxy150489 msec_delay(1);
6924919Sxy150489 timeout--;
6934919Sxy150489 }
6944919Sxy150489 if (!timeout) {
6954919Sxy150489 DEBUGOUT("MNG configuration cycle has not completed.\n");
6964919Sxy150489 ret_val = -E1000_ERR_RESET;
6974919Sxy150489 goto out;
6984919Sxy150489 }
6994919Sxy150489
7004919Sxy150489 out:
7014919Sxy150489 return (ret_val);
7024919Sxy150489 }
7034919Sxy150489
7044919Sxy150489 /*
7054919Sxy150489 * e1000_phy_force_speed_duplex_80003es2lan - Force PHY speed and duplex
7064919Sxy150489 * @hw: pointer to the HW structure
7074919Sxy150489 *
7084919Sxy150489 * Force the speed and duplex settings onto the PHY. This is a
7094919Sxy150489 * function pointer entry point called by the phy module.
7104919Sxy150489 */
7114919Sxy150489 static s32
e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw * hw)7124919Sxy150489 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
7134919Sxy150489 {
71410680SMin.Xu@Sun.COM s32 ret_val = E1000_SUCCESS;
7154919Sxy150489 u16 phy_data;
7166735Scc210113 bool link;
7174919Sxy150489
7184919Sxy150489 DEBUGFUNC("e1000_phy_force_speed_duplex_80003es2lan");
7194919Sxy150489
7206735Scc210113 if (!(hw->phy.ops.read_reg))
7216735Scc210113 goto out;
7226735Scc210113
7234919Sxy150489 /*
7244919Sxy150489 * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
7254919Sxy150489 * forced whenever speed and duplex are forced.
7264919Sxy150489 */
7276735Scc210113 ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
7284919Sxy150489 if (ret_val)
7294919Sxy150489 goto out;
7304919Sxy150489
7314919Sxy150489 phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO;
7326735Scc210113 ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
7334919Sxy150489 if (ret_val)
7344919Sxy150489 goto out;
7354919Sxy150489
7364919Sxy150489 DEBUGOUT1("GG82563 PSCR: %X\n", phy_data);
7374919Sxy150489
7386735Scc210113 ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_data);
7394919Sxy150489 if (ret_val)
7404919Sxy150489 goto out;
7414919Sxy150489
7424919Sxy150489 e1000_phy_force_speed_duplex_setup(hw, &phy_data);
7434919Sxy150489
7444919Sxy150489 /* Reset the phy to commit changes. */
7454919Sxy150489 phy_data |= MII_CR_RESET;
7464919Sxy150489
7476735Scc210113 ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_data);
7484919Sxy150489 if (ret_val)
7494919Sxy150489 goto out;
7504919Sxy150489
7514919Sxy150489 usec_delay(1);
7524919Sxy150489
7536735Scc210113 if (hw->phy.autoneg_wait_to_complete) {
7544919Sxy150489 DEBUGOUT("Waiting for forced speed/duplex link "
7554919Sxy150489 "on GG82563 phy.\n");
7564919Sxy150489
7574919Sxy150489 ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
7584919Sxy150489 100000, &link);
7594919Sxy150489 if (ret_val)
7604919Sxy150489 goto out;
7614919Sxy150489
7624919Sxy150489 if (!link) {
7634919Sxy150489 /*
7644919Sxy150489 * We didn't get link.
7654919Sxy150489 * Reset the DSP and cross our fingers.
7664919Sxy150489 */
7674919Sxy150489 ret_val = e1000_phy_reset_dsp_generic(hw);
7684919Sxy150489 if (ret_val)
7694919Sxy150489 goto out;
7704919Sxy150489 }
7714919Sxy150489
7724919Sxy150489 /* Try once more */
7734919Sxy150489 ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
7744919Sxy150489 100000, &link);
7754919Sxy150489 if (ret_val)
7764919Sxy150489 goto out;
7774919Sxy150489 }
7784919Sxy150489
7796735Scc210113 ret_val =
7806735Scc210113 hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data);
7814919Sxy150489 if (ret_val)
7824919Sxy150489 goto out;
7834919Sxy150489
7844919Sxy150489 /*
7854919Sxy150489 * Resetting the phy means we need to verify the TX_CLK corresponds
7864919Sxy150489 * to the link speed. 10Mbps -> 2.5MHz, else 25MHz.
7874919Sxy150489 */
7884919Sxy150489 phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
7894919Sxy150489 if (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED)
7904919Sxy150489 phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5;
7914919Sxy150489 else
7924919Sxy150489 phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25;
7934919Sxy150489
7944919Sxy150489 /*
7954919Sxy150489 * In addition, we must re-enable CRS on Tx for both half and full
7964919Sxy150489 * duplex.
7974919Sxy150489 */
7984919Sxy150489 phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
7996735Scc210113 ret_val =
8006735Scc210113 hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data);
8014919Sxy150489
8024919Sxy150489 out:
8034919Sxy150489 return (ret_val);
8044919Sxy150489 }
8054919Sxy150489
8064919Sxy150489 /*
8074919Sxy150489 * e1000_get_cable_length_80003es2lan - Set approximate cable length
8084919Sxy150489 * @hw: pointer to the HW structure
8094919Sxy150489 *
8104919Sxy150489 * Find the approximate cable length as measured by the GG82563 PHY.
8114919Sxy150489 * This is a function pointer entry point called by the phy module.
8124919Sxy150489 */
8134919Sxy150489 static s32
e1000_get_cable_length_80003es2lan(struct e1000_hw * hw)8144919Sxy150489 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
8154919Sxy150489 {
8164919Sxy150489 struct e1000_phy_info *phy = &hw->phy;
8176735Scc210113 s32 ret_val = E1000_SUCCESS;
8184919Sxy150489 u16 phy_data, index;
8194919Sxy150489
8204919Sxy150489 DEBUGFUNC("e1000_get_cable_length_80003es2lan");
8214919Sxy150489
8226735Scc210113 if (!(hw->phy.ops.read_reg))
8236735Scc210113 goto out;
8246735Scc210113
8256735Scc210113 ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_DSP_DISTANCE, &phy_data);
8264919Sxy150489 if (ret_val)
8274919Sxy150489 goto out;
8284919Sxy150489
8294919Sxy150489 index = phy_data & GG82563_DSPD_CABLE_LENGTH;
8308479SChenlu.Chen@Sun.COM
83110680SMin.Xu@Sun.COM if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5) {
83210680SMin.Xu@Sun.COM ret_val = E1000_ERR_PHY;
83310680SMin.Xu@Sun.COM goto out;
83410680SMin.Xu@Sun.COM }
8354919Sxy150489
83610680SMin.Xu@Sun.COM phy->min_cable_length = e1000_gg82563_cable_length_table[index];
83710680SMin.Xu@Sun.COM phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5];
83810680SMin.Xu@Sun.COM
83910680SMin.Xu@Sun.COM phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
8404919Sxy150489
8414919Sxy150489 out:
8424919Sxy150489 return (ret_val);
8434919Sxy150489 }
8444919Sxy150489
8454919Sxy150489 /*
8464919Sxy150489 * e1000_get_link_up_info_80003es2lan - Report speed and duplex
8474919Sxy150489 * @hw: pointer to the HW structure
8484919Sxy150489 * @speed: pointer to speed buffer
8494919Sxy150489 * @duplex: pointer to duplex buffer
8504919Sxy150489 *
8514919Sxy150489 * Retrieve the current speed and duplex configuration.
8524919Sxy150489 */
8534919Sxy150489 static s32
e1000_get_link_up_info_80003es2lan(struct e1000_hw * hw,u16 * speed,u16 * duplex)8544919Sxy150489 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, u16 *duplex)
8554919Sxy150489 {
8564919Sxy150489 s32 ret_val;
8574919Sxy150489
8584919Sxy150489 DEBUGFUNC("e1000_get_link_up_info_80003es2lan");
8594919Sxy150489
8606735Scc210113 if (hw->phy.media_type == e1000_media_type_copper) {
8614919Sxy150489 ret_val = e1000_get_speed_and_duplex_copper_generic(hw,
8624919Sxy150489 speed,
8634919Sxy150489 duplex);
8648479SChenlu.Chen@Sun.COM hw->phy.ops.cfg_on_link_up(hw);
8654919Sxy150489 } else {
8664919Sxy150489 ret_val = e1000_get_speed_and_duplex_fiber_serdes_generic(hw,
8674919Sxy150489 speed,
8684919Sxy150489 duplex);
8694919Sxy150489 }
8704919Sxy150489
8714919Sxy150489 return (ret_val);
8724919Sxy150489 }
8734919Sxy150489
8744919Sxy150489 /*
8754919Sxy150489 * e1000_reset_hw_80003es2lan - Reset the ESB2 controller
8764919Sxy150489 * @hw: pointer to the HW structure
8774919Sxy150489 *
8784919Sxy150489 * Perform a global reset to the ESB2 controller.
8794919Sxy150489 */
8804919Sxy150489 static s32
e1000_reset_hw_80003es2lan(struct e1000_hw * hw)8814919Sxy150489 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
8824919Sxy150489 {
8837426SChenliang.Xu@Sun.COM u32 ctrl;
8844919Sxy150489 s32 ret_val;
8854919Sxy150489
8864919Sxy150489 DEBUGFUNC("e1000_reset_hw_80003es2lan");
8874919Sxy150489
8884919Sxy150489 /*
8894919Sxy150489 * Prevent the PCI-E bus from sticking if there is no TLP connection
8904919Sxy150489 * on the last TLP read/write transaction when MAC is reset.
8914919Sxy150489 */
8924919Sxy150489 ret_val = e1000_disable_pcie_master_generic(hw);
893*11143SGuoqing.Zhu@Sun.COM if (ret_val) {
894*11143SGuoqing.Zhu@Sun.COM /* EMPTY */
8954919Sxy150489 DEBUGOUT("PCI-E Master disable polling has failed.\n");
896*11143SGuoqing.Zhu@Sun.COM }
8974919Sxy150489
8984919Sxy150489 DEBUGOUT("Masking off all interrupts\n");
8994919Sxy150489 E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
9004919Sxy150489
9014919Sxy150489 E1000_WRITE_REG(hw, E1000_RCTL, 0);
9024919Sxy150489 E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
9034919Sxy150489 E1000_WRITE_FLUSH(hw);
9044919Sxy150489
9054919Sxy150489 msec_delay(10);
9064919Sxy150489
9074919Sxy150489 ctrl = E1000_READ_REG(hw, E1000_CTRL);
9084919Sxy150489
9098479SChenlu.Chen@Sun.COM ret_val = e1000_acquire_phy_80003es2lan(hw);
9104919Sxy150489 DEBUGOUT("Issuing a global reset to MAC\n");
9114919Sxy150489 E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
9128479SChenlu.Chen@Sun.COM e1000_release_phy_80003es2lan(hw);
9134919Sxy150489
9144919Sxy150489 ret_val = e1000_get_auto_rd_done_generic(hw);
9154919Sxy150489 if (ret_val)
9164919Sxy150489 /* We don't want to continue accessing MAC registers. */
9174919Sxy150489 goto out;
9184919Sxy150489
9194919Sxy150489 /* Clear any pending interrupt events. */
9204919Sxy150489 E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
9217426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_ICR);
9224919Sxy150489
92310680SMin.Xu@Sun.COM ret_val = e1000_check_alt_mac_addr_generic(hw);
9246735Scc210113
9254919Sxy150489 out:
9264919Sxy150489 return (ret_val);
9274919Sxy150489 }
9284919Sxy150489
9294919Sxy150489 /*
9304919Sxy150489 * e1000_init_hw_80003es2lan - Initialize the ESB2 controller
9314919Sxy150489 * @hw: pointer to the HW structure
9324919Sxy150489 *
9334919Sxy150489 * Initialize the hw bits, LED, VFTA, MTA, link and hw counters.
9344919Sxy150489 */
9354919Sxy150489 static s32
e1000_init_hw_80003es2lan(struct e1000_hw * hw)9364919Sxy150489 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
9374919Sxy150489 {
9384919Sxy150489 struct e1000_mac_info *mac = &hw->mac;
9394919Sxy150489 u32 reg_data;
9404919Sxy150489 s32 ret_val;
9414919Sxy150489 u16 i;
9424919Sxy150489
9434919Sxy150489 DEBUGFUNC("e1000_init_hw_80003es2lan");
9444919Sxy150489
9454919Sxy150489 e1000_initialize_hw_bits_80003es2lan(hw);
9464919Sxy150489
9474919Sxy150489 /* Initialize identification LED */
94810680SMin.Xu@Sun.COM ret_val = mac->ops.id_led_init(hw);
9494919Sxy150489 if (ret_val) {
950*11143SGuoqing.Zhu@Sun.COM /* EMPTY */
9514919Sxy150489 DEBUGOUT("Error initializing identification LED\n");
9526735Scc210113 /* This is not fatal and we should not stop init due to this */
9534919Sxy150489 }
9544919Sxy150489
9554919Sxy150489 /* Disabling VLAN filtering */
9564919Sxy150489 DEBUGOUT("Initializing the IEEE VLAN\n");
9576735Scc210113 mac->ops.clear_vfta(hw);
9584919Sxy150489
9594919Sxy150489 /* Setup the receive address. */
9604919Sxy150489 e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
9614919Sxy150489
9624919Sxy150489 /* Zero out the Multicast HASH table */
9634919Sxy150489 DEBUGOUT("Zeroing the MTA\n");
9644919Sxy150489 for (i = 0; i < mac->mta_reg_count; i++)
9654919Sxy150489 E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
9664919Sxy150489
9674919Sxy150489 /* Setup link and flow control */
9686735Scc210113 ret_val = mac->ops.setup_link(hw);
9694919Sxy150489
9704919Sxy150489 /* Set the transmit descriptor write-back policy */
9716735Scc210113 reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
9724919Sxy150489 reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
9734919Sxy150489 E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
9746735Scc210113 E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
9754919Sxy150489
9764919Sxy150489 /* ...for both queues. */
9776735Scc210113 reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
9784919Sxy150489 reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
9794919Sxy150489 E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
9806735Scc210113 E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
9814919Sxy150489
9824919Sxy150489 /* Enable retransmit on late collisions */
9834919Sxy150489 reg_data = E1000_READ_REG(hw, E1000_TCTL);
9844919Sxy150489 reg_data |= E1000_TCTL_RTLC;
9854919Sxy150489 E1000_WRITE_REG(hw, E1000_TCTL, reg_data);
9864919Sxy150489
9874919Sxy150489 /* Configure Gigabit Carry Extend Padding */
9884919Sxy150489 reg_data = E1000_READ_REG(hw, E1000_TCTL_EXT);
9894919Sxy150489 reg_data &= ~E1000_TCTL_EXT_GCEX_MASK;
9904919Sxy150489 reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN;
9914919Sxy150489 E1000_WRITE_REG(hw, E1000_TCTL_EXT, reg_data);
9924919Sxy150489
9934919Sxy150489 /* Configure Transmit Inter-Packet Gap */
9944919Sxy150489 reg_data = E1000_READ_REG(hw, E1000_TIPG);
9954919Sxy150489 reg_data &= ~E1000_TIPG_IPGT_MASK;
9964919Sxy150489 reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
9974919Sxy150489 E1000_WRITE_REG(hw, E1000_TIPG, reg_data);
9984919Sxy150489
9994919Sxy150489 reg_data = E1000_READ_REG_ARRAY(hw, E1000_FFLT, 0x0001);
10004919Sxy150489 reg_data &= ~0x00100000;
10014919Sxy150489 E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data);
10024919Sxy150489
100310680SMin.Xu@Sun.COM /* default to true to enable the MDIC W/A */
100410680SMin.Xu@Sun.COM hw->dev_spec._80003es2lan.mdic_wa_enable = true;
100510680SMin.Xu@Sun.COM
100610680SMin.Xu@Sun.COM ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
100710680SMin.Xu@Sun.COM E1000_KMRNCTRLSTA_OFFSET >>
100810680SMin.Xu@Sun.COM E1000_KMRNCTRLSTA_OFFSET_SHIFT,
100910680SMin.Xu@Sun.COM &i);
101010680SMin.Xu@Sun.COM if (!ret_val) {
101110680SMin.Xu@Sun.COM if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) ==
101210680SMin.Xu@Sun.COM E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO)
101310680SMin.Xu@Sun.COM hw->dev_spec._80003es2lan.mdic_wa_enable = false;
101410680SMin.Xu@Sun.COM }
101510680SMin.Xu@Sun.COM
10164919Sxy150489 /*
10174919Sxy150489 * Clear all of the statistics registers (clear on read). It is
10184919Sxy150489 * important that we do this after we have tried to establish link
10194919Sxy150489 * because the symbol error count will increment wildly if there
10204919Sxy150489 * is no link.
10214919Sxy150489 */
10224919Sxy150489 e1000_clear_hw_cntrs_80003es2lan(hw);
10234919Sxy150489
10244919Sxy150489 return (ret_val);
10254919Sxy150489 }
10264919Sxy150489
10274919Sxy150489 /*
10284919Sxy150489 * e1000_initialize_hw_bits_80003es2lan - Init hw bits of ESB2
10294919Sxy150489 * @hw: pointer to the HW structure
10304919Sxy150489 *
10314919Sxy150489 * Initializes required hardware-dependent bits needed for normal operation.
10324919Sxy150489 */
10334919Sxy150489 static void
e1000_initialize_hw_bits_80003es2lan(struct e1000_hw * hw)10344919Sxy150489 e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
10354919Sxy150489 {
10364919Sxy150489 u32 reg;
10374919Sxy150489
10384919Sxy150489 DEBUGFUNC("e1000_initialize_hw_bits_80003es2lan");
10394919Sxy150489
10404919Sxy150489 /* Transmit Descriptor Control 0 */
10416735Scc210113 reg = E1000_READ_REG(hw, E1000_TXDCTL(0));
10424919Sxy150489 reg |= (1 << 22);
10436735Scc210113 E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg);
10444919Sxy150489
10454919Sxy150489 /* Transmit Descriptor Control 1 */
10466735Scc210113 reg = E1000_READ_REG(hw, E1000_TXDCTL(1));
10474919Sxy150489 reg |= (1 << 22);
10486735Scc210113 E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg);
10494919Sxy150489
10504919Sxy150489 /* Transmit Arbitration Control 0 */
10516735Scc210113 reg = E1000_READ_REG(hw, E1000_TARC(0));
10524919Sxy150489 reg &= ~(0xF << 27); /* 30:27 */
10536735Scc210113 if (hw->phy.media_type != e1000_media_type_copper)
10544919Sxy150489 reg &= ~(1 << 20);
10556735Scc210113 E1000_WRITE_REG(hw, E1000_TARC(0), reg);
10564919Sxy150489
10574919Sxy150489 /* Transmit Arbitration Control 1 */
10586735Scc210113 reg = E1000_READ_REG(hw, E1000_TARC(1));
10594919Sxy150489 if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR)
10604919Sxy150489 reg &= ~(1 << 28);
10614919Sxy150489 else
10624919Sxy150489 reg |= (1 << 28);
10636735Scc210113 E1000_WRITE_REG(hw, E1000_TARC(1), reg);
10644919Sxy150489 }
10654919Sxy150489
10664919Sxy150489 /*
10674919Sxy150489 * e1000_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link
10684919Sxy150489 * @hw: pointer to the HW structure
10694919Sxy150489 *
10704919Sxy150489 * Setup some GG82563 PHY registers for obtaining link
10714919Sxy150489 */
10724919Sxy150489 static s32
e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw * hw)10734919Sxy150489 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
10744919Sxy150489 {
10754919Sxy150489 struct e1000_phy_info *phy = &hw->phy;
10764919Sxy150489 s32 ret_val;
10774919Sxy150489 u32 ctrl_ext;
10788479SChenlu.Chen@Sun.COM u16 data;
10794919Sxy150489
10804919Sxy150489 DEBUGFUNC("e1000_copper_link_setup_gg82563_80003es2lan");
10814919Sxy150489
10824919Sxy150489 if (!phy->reset_disable) {
10836735Scc210113 ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
10844919Sxy150489 &data);
10854919Sxy150489 if (ret_val)
10864919Sxy150489 goto out;
10874919Sxy150489
10884919Sxy150489 data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
10894919Sxy150489 /* Use 25MHz for both link down and 1000Base-T for Tx clock. */
10904919Sxy150489 data |= GG82563_MSCR_TX_CLK_1000MBPS_25;
10914919Sxy150489
10926735Scc210113 ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
10934919Sxy150489 data);
10944919Sxy150489 if (ret_val)
10954919Sxy150489 goto out;
10964919Sxy150489
10974919Sxy150489 /*
10984919Sxy150489 * Options:
10994919Sxy150489 * MDI/MDI-X = 0 (default)
11004919Sxy150489 * 0 - Auto for all speeds
11014919Sxy150489 * 1 - MDI mode
11024919Sxy150489 * 2 - MDI-X mode
11034919Sxy150489 * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
11044919Sxy150489 */
11056735Scc210113 ret_val =
11066735Scc210113 hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL, &data);
11074919Sxy150489 if (ret_val)
11084919Sxy150489 goto out;
11094919Sxy150489
11104919Sxy150489 data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
11114919Sxy150489
11124919Sxy150489 switch (phy->mdix) {
11134919Sxy150489 case 1:
11144919Sxy150489 data |= GG82563_PSCR_CROSSOVER_MODE_MDI;
11154919Sxy150489 break;
11164919Sxy150489 case 2:
11174919Sxy150489 data |= GG82563_PSCR_CROSSOVER_MODE_MDIX;
11184919Sxy150489 break;
11194919Sxy150489 case 0:
11204919Sxy150489 default:
11214919Sxy150489 data |= GG82563_PSCR_CROSSOVER_MODE_AUTO;
11224919Sxy150489 break;
11234919Sxy150489 }
11244919Sxy150489
11254919Sxy150489 /*
11264919Sxy150489 * Options:
11274919Sxy150489 * disable_polarity_correction = 0 (default)
11284919Sxy150489 * Automatic Correction for Reversed Cable Polarity
11294919Sxy150489 * 0 - Disabled
11304919Sxy150489 * 1 - Enabled
11314919Sxy150489 */
11324919Sxy150489 data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
11334919Sxy150489 if (phy->disable_polarity_correction)
11344919Sxy150489 data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
11354919Sxy150489
11366735Scc210113 ret_val =
11376735Scc210113 hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, data);
11384919Sxy150489 if (ret_val)
11394919Sxy150489 goto out;
11404919Sxy150489
11414919Sxy150489 /* SW Reset the PHY so all changes take effect */
11426735Scc210113 ret_val = hw->phy.ops.commit(hw);
11434919Sxy150489 if (ret_val) {
11444919Sxy150489 DEBUGOUT("Error Resetting the PHY\n");
11454919Sxy150489 goto out;
11464919Sxy150489 }
11474919Sxy150489
11484919Sxy150489 }
11494919Sxy150489
11506735Scc210113 /* Bypass Rx and Tx FIFO's */
11518479SChenlu.Chen@Sun.COM ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
11524919Sxy150489 E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
11534919Sxy150489 E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
11544919Sxy150489 E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
11554919Sxy150489 if (ret_val)
11564919Sxy150489 goto out;
11574919Sxy150489
11588479SChenlu.Chen@Sun.COM ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
11596735Scc210113 E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
11606735Scc210113 &data);
11616735Scc210113 if (ret_val)
11626735Scc210113 goto out;
11636735Scc210113
11646735Scc210113 data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
11658479SChenlu.Chen@Sun.COM ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
11666735Scc210113 E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
11676735Scc210113 data);
11686735Scc210113 if (ret_val)
11696735Scc210113 goto out;
11706735Scc210113
11716735Scc210113 ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL_2, &data);
11724919Sxy150489 if (ret_val)
11734919Sxy150489 goto out;
11744919Sxy150489
11754919Sxy150489 data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
11766735Scc210113 ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL_2, data);
11774919Sxy150489 if (ret_val)
11784919Sxy150489 goto out;
11794919Sxy150489
11804919Sxy150489 ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
11814919Sxy150489 ctrl_ext &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
11824919Sxy150489 E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
11834919Sxy150489
11846735Scc210113 ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, &data);
11854919Sxy150489 if (ret_val)
11864919Sxy150489 goto out;
11874919Sxy150489
11884919Sxy150489 /*
11894919Sxy150489 * Do not init these registers when the HW is in IAMT mode, since the
11904919Sxy150489 * firmware will have already initialized them. We only initialize
11914919Sxy150489 * them if the HW is not in IAMT mode.
11924919Sxy150489 */
11936735Scc210113 if (!(hw->mac.ops.check_mng_mode(hw))) {
11944919Sxy150489 /* Enable Electrical Idle on the PHY */
11954919Sxy150489 data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
119610680SMin.Xu@Sun.COM ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
11974919Sxy150489 data);
11984919Sxy150489 if (ret_val)
11994919Sxy150489 goto out;
120010680SMin.Xu@Sun.COM ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
12018479SChenlu.Chen@Sun.COM &data);
12026735Scc210113
12038479SChenlu.Chen@Sun.COM if (ret_val)
12048479SChenlu.Chen@Sun.COM goto out;
12054919Sxy150489
12064919Sxy150489 data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
120710680SMin.Xu@Sun.COM ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
12084919Sxy150489 data);
12094919Sxy150489
12104919Sxy150489 if (ret_val)
12114919Sxy150489 goto out;
12124919Sxy150489 }
12134919Sxy150489
12144919Sxy150489 /*
12154919Sxy150489 * Workaround: Disable padding in Kumeran interface in the MAC
12164919Sxy150489 * and in the PHY to avoid CRC errors.
12174919Sxy150489 */
12186735Scc210113 ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_INBAND_CTRL, &data);
12194919Sxy150489 if (ret_val)
12204919Sxy150489 goto out;
12214919Sxy150489
12224919Sxy150489 data |= GG82563_ICR_DIS_PADDING;
12236735Scc210113 ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_INBAND_CTRL, data);
12244919Sxy150489 if (ret_val)
12254919Sxy150489 goto out;
12264919Sxy150489
12274919Sxy150489 out:
12284919Sxy150489 return (ret_val);
12294919Sxy150489 }
12304919Sxy150489
12314919Sxy150489 /*
12324919Sxy150489 * e1000_setup_copper_link_80003es2lan - Setup Copper Link for ESB2
12334919Sxy150489 * @hw: pointer to the HW structure
12344919Sxy150489 *
12354919Sxy150489 * Essentially a wrapper for setting up all things "copper" related.
12364919Sxy150489 * This is a function pointer entry point called by the mac module.
12374919Sxy150489 */
12384919Sxy150489 static s32
e1000_setup_copper_link_80003es2lan(struct e1000_hw * hw)12394919Sxy150489 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
12404919Sxy150489 {
12414919Sxy150489 u32 ctrl;
12424919Sxy150489 s32 ret_val;
12434919Sxy150489 u16 reg_data;
12444919Sxy150489
12454919Sxy150489 DEBUGFUNC("e1000_setup_copper_link_80003es2lan");
12464919Sxy150489
12474919Sxy150489 ctrl = E1000_READ_REG(hw, E1000_CTRL);
12484919Sxy150489 ctrl |= E1000_CTRL_SLU;
12494919Sxy150489 ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
12504919Sxy150489 E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
12514919Sxy150489
12524919Sxy150489 /*
12534919Sxy150489 * Set the mac to wait the maximum time between each
12544919Sxy150489 * iteration and increase the max iterations when
12554919Sxy150489 * polling the phy; this fixes erroneous timeouts at 10Mbps.
12564919Sxy150489 */
12578479SChenlu.Chen@Sun.COM ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4),
12587607STed.You@Sun.COM 0xFFFF);
12594919Sxy150489 if (ret_val)
12604919Sxy150489 goto out;
12618479SChenlu.Chen@Sun.COM ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
12627607STed.You@Sun.COM ®_data);
12634919Sxy150489 if (ret_val)
12644919Sxy150489 goto out;
12654919Sxy150489 reg_data |= 0x3F;
12668479SChenlu.Chen@Sun.COM ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
12677607STed.You@Sun.COM reg_data);
12684919Sxy150489 if (ret_val)
12694919Sxy150489 goto out;
12708479SChenlu.Chen@Sun.COM ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
12714919Sxy150489 E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
12724919Sxy150489 ®_data);
12734919Sxy150489 if (ret_val)
12744919Sxy150489 goto out;
12754919Sxy150489 reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
12768479SChenlu.Chen@Sun.COM ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
12774919Sxy150489 E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
12784919Sxy150489 reg_data);
12794919Sxy150489 if (ret_val)
12804919Sxy150489 goto out;
12814919Sxy150489
12824919Sxy150489 ret_val = e1000_copper_link_setup_gg82563_80003es2lan(hw);
12834919Sxy150489 if (ret_val)
12844919Sxy150489 goto out;
12854919Sxy150489
12864919Sxy150489 ret_val = e1000_setup_copper_link_generic(hw);
12874919Sxy150489
12884919Sxy150489 out:
12894919Sxy150489 return (ret_val);
12904919Sxy150489 }
12914919Sxy150489
12924919Sxy150489 /*
12938479SChenlu.Chen@Sun.COM * e1000_cfg_on_link_up_80003es2lan - es2 link configuration after link-up
12948479SChenlu.Chen@Sun.COM * @hw: pointer to the HW structure
12958479SChenlu.Chen@Sun.COM * @duplex: current duplex setting
12968479SChenlu.Chen@Sun.COM *
12978479SChenlu.Chen@Sun.COM * Configure the KMRN interface by applying last minute quirks for
12988479SChenlu.Chen@Sun.COM * 10/100 operation.
12998479SChenlu.Chen@Sun.COM */
13008479SChenlu.Chen@Sun.COM static s32
e1000_cfg_on_link_up_80003es2lan(struct e1000_hw * hw)13018479SChenlu.Chen@Sun.COM e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
13028479SChenlu.Chen@Sun.COM {
13038479SChenlu.Chen@Sun.COM s32 ret_val = E1000_SUCCESS;
13048479SChenlu.Chen@Sun.COM u16 speed;
13058479SChenlu.Chen@Sun.COM u16 duplex;
13068479SChenlu.Chen@Sun.COM
13078479SChenlu.Chen@Sun.COM DEBUGFUNC("e1000_configure_on_link_up");
13088479SChenlu.Chen@Sun.COM
13098479SChenlu.Chen@Sun.COM if (hw->phy.media_type == e1000_media_type_copper) {
13108479SChenlu.Chen@Sun.COM
13118479SChenlu.Chen@Sun.COM ret_val = e1000_get_speed_and_duplex_copper_generic(hw,
13128479SChenlu.Chen@Sun.COM &speed,
13138479SChenlu.Chen@Sun.COM &duplex);
13148479SChenlu.Chen@Sun.COM if (ret_val)
13158479SChenlu.Chen@Sun.COM goto out;
13168479SChenlu.Chen@Sun.COM
13178479SChenlu.Chen@Sun.COM if (speed == SPEED_1000)
13188479SChenlu.Chen@Sun.COM ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw);
13198479SChenlu.Chen@Sun.COM else
13208479SChenlu.Chen@Sun.COM ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex);
13218479SChenlu.Chen@Sun.COM }
13228479SChenlu.Chen@Sun.COM
13238479SChenlu.Chen@Sun.COM out:
13248479SChenlu.Chen@Sun.COM return (ret_val);
13258479SChenlu.Chen@Sun.COM }
13268479SChenlu.Chen@Sun.COM
13278479SChenlu.Chen@Sun.COM /*
13284919Sxy150489 * e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation
13294919Sxy150489 * @hw: pointer to the HW structure
13304919Sxy150489 * @duplex: current duplex setting
13314919Sxy150489 *
13324919Sxy150489 * Configure the KMRN interface by applying last minute quirks for
13334919Sxy150489 * 10/100 operation.
13344919Sxy150489 */
13354919Sxy150489 static s32
e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw * hw,u16 duplex)13364919Sxy150489 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
13374919Sxy150489 {
13384919Sxy150489 s32 ret_val = E1000_SUCCESS;
13394919Sxy150489 u32 tipg;
13404919Sxy150489 u32 i = 0;
13414919Sxy150489 u16 reg_data, reg_data2;
13424919Sxy150489
13434919Sxy150489 DEBUGFUNC("e1000_configure_kmrn_for_10_100");
13444919Sxy150489
13454919Sxy150489 reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
13468479SChenlu.Chen@Sun.COM ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
13474919Sxy150489 E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
13484919Sxy150489 reg_data);
13494919Sxy150489 if (ret_val)
13504919Sxy150489 goto out;
13514919Sxy150489
13524919Sxy150489 /* Configure Transmit Inter-Packet Gap */
13534919Sxy150489 tipg = E1000_READ_REG(hw, E1000_TIPG);
13544919Sxy150489 tipg &= ~E1000_TIPG_IPGT_MASK;
13554919Sxy150489 tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN;
13564919Sxy150489 E1000_WRITE_REG(hw, E1000_TIPG, tipg);
13574919Sxy150489
13584919Sxy150489
13594919Sxy150489 do {
13606735Scc210113 ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
13614919Sxy150489 ®_data);
13624919Sxy150489 if (ret_val)
13634919Sxy150489 goto out;
13644919Sxy150489
13656735Scc210113 ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
13664919Sxy150489 ®_data2);
13674919Sxy150489 if (ret_val)
13684919Sxy150489 goto out;
13694919Sxy150489 i++;
13704919Sxy150489 } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
13714919Sxy150489
13724919Sxy150489 if (duplex == HALF_DUPLEX)
13734919Sxy150489 reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
13744919Sxy150489 else
13754919Sxy150489 reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
13764919Sxy150489
13776735Scc210113 ret_val =
13786735Scc210113 hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
13794919Sxy150489
13804919Sxy150489 out:
13814919Sxy150489 return (ret_val);
13824919Sxy150489 }
13834919Sxy150489
13844919Sxy150489 /*
13854919Sxy150489 * e1000_cfg_kmrn_1000_80003es2lan - Apply "quirks" for gigabit operation
13864919Sxy150489 * @hw: pointer to the HW structure
13874919Sxy150489 *
13884919Sxy150489 * Configure the KMRN interface by applying last minute quirks for
13894919Sxy150489 * gigabit operation.
13904919Sxy150489 */
13914919Sxy150489 static s32
e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw * hw)13924919Sxy150489 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
13934919Sxy150489 {
13944919Sxy150489 s32 ret_val = E1000_SUCCESS;
13954919Sxy150489 u16 reg_data, reg_data2;
13964919Sxy150489 u32 tipg;
13974919Sxy150489 u32 i = 0;
13984919Sxy150489
13994919Sxy150489 DEBUGFUNC("e1000_configure_kmrn_for_1000");
14004919Sxy150489
14014919Sxy150489 reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
14028479SChenlu.Chen@Sun.COM ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
14034919Sxy150489 E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
14044919Sxy150489 reg_data);
14054919Sxy150489 if (ret_val)
14064919Sxy150489 goto out;
14074919Sxy150489
14084919Sxy150489 /* Configure Transmit Inter-Packet Gap */
14094919Sxy150489 tipg = E1000_READ_REG(hw, E1000_TIPG);
14104919Sxy150489 tipg &= ~E1000_TIPG_IPGT_MASK;
14114919Sxy150489 tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
14124919Sxy150489 E1000_WRITE_REG(hw, E1000_TIPG, tipg);
14134919Sxy150489
14144919Sxy150489
14154919Sxy150489 do {
14166735Scc210113 ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
14174919Sxy150489 ®_data);
14184919Sxy150489 if (ret_val)
14194919Sxy150489 goto out;
14204919Sxy150489
14216735Scc210113 ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
14224919Sxy150489 ®_data2);
14234919Sxy150489 if (ret_val)
14244919Sxy150489 goto out;
14254919Sxy150489 i++;
14264919Sxy150489 } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
14274919Sxy150489
14284919Sxy150489 reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
14296735Scc210113 ret_val =
14306735Scc210113 hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
14314919Sxy150489
14324919Sxy150489 out:
14334919Sxy150489 return (ret_val);
14344919Sxy150489 }
14354919Sxy150489
14364919Sxy150489 /*
14378479SChenlu.Chen@Sun.COM * e1000_read_kmrn_reg_80003es2lan - Read kumeran register
14388479SChenlu.Chen@Sun.COM * @hw: pointer to the HW structure
14398479SChenlu.Chen@Sun.COM * @offset: register offset to be read
14408479SChenlu.Chen@Sun.COM * @data: pointer to the read data
14418479SChenlu.Chen@Sun.COM *
14428479SChenlu.Chen@Sun.COM * Acquire semaphore, then read the PHY register at offset
14438479SChenlu.Chen@Sun.COM * using the kumeran interface. The information retrieved is stored in data.
14448479SChenlu.Chen@Sun.COM * Release the semaphore before exiting.
14458479SChenlu.Chen@Sun.COM */
144610680SMin.Xu@Sun.COM static s32
e1000_read_kmrn_reg_80003es2lan(struct e1000_hw * hw,u32 offset,u16 * data)14478479SChenlu.Chen@Sun.COM e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data)
14488479SChenlu.Chen@Sun.COM {
14498479SChenlu.Chen@Sun.COM u32 kmrnctrlsta;
14508479SChenlu.Chen@Sun.COM s32 ret_val = E1000_SUCCESS;
14518479SChenlu.Chen@Sun.COM
14528479SChenlu.Chen@Sun.COM DEBUGFUNC("e1000_read_kmrn_reg_80003es2lan");
14538479SChenlu.Chen@Sun.COM
14548479SChenlu.Chen@Sun.COM ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
14558479SChenlu.Chen@Sun.COM if (ret_val)
14568479SChenlu.Chen@Sun.COM goto out;
14578479SChenlu.Chen@Sun.COM
14588479SChenlu.Chen@Sun.COM kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
14598479SChenlu.Chen@Sun.COM E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
14608479SChenlu.Chen@Sun.COM E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
14618479SChenlu.Chen@Sun.COM
14628479SChenlu.Chen@Sun.COM usec_delay(2);
14638479SChenlu.Chen@Sun.COM
14648479SChenlu.Chen@Sun.COM kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA);
14658479SChenlu.Chen@Sun.COM *data = (u16)kmrnctrlsta;
14668479SChenlu.Chen@Sun.COM
14678479SChenlu.Chen@Sun.COM e1000_release_mac_csr_80003es2lan(hw);
14688479SChenlu.Chen@Sun.COM
14698479SChenlu.Chen@Sun.COM out:
14708479SChenlu.Chen@Sun.COM return (ret_val);
14718479SChenlu.Chen@Sun.COM }
14728479SChenlu.Chen@Sun.COM
14738479SChenlu.Chen@Sun.COM /*
14748479SChenlu.Chen@Sun.COM * e1000_write_kmrn_reg_80003es2lan - Write kumeran register
14758479SChenlu.Chen@Sun.COM * @hw: pointer to the HW structure
14768479SChenlu.Chen@Sun.COM * @offset: register offset to write to
14778479SChenlu.Chen@Sun.COM * @data: data to write at register offset
14788479SChenlu.Chen@Sun.COM *
14798479SChenlu.Chen@Sun.COM * Acquire semaphore, then write the data to PHY register
14808479SChenlu.Chen@Sun.COM * at the offset using the kumeran interface. Release semaphore
14818479SChenlu.Chen@Sun.COM * before exiting.
14828479SChenlu.Chen@Sun.COM */
148310680SMin.Xu@Sun.COM static s32
e1000_write_kmrn_reg_80003es2lan(struct e1000_hw * hw,u32 offset,u16 data)14848479SChenlu.Chen@Sun.COM e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data)
14858479SChenlu.Chen@Sun.COM {
14868479SChenlu.Chen@Sun.COM u32 kmrnctrlsta;
14878479SChenlu.Chen@Sun.COM s32 ret_val = E1000_SUCCESS;
14888479SChenlu.Chen@Sun.COM
14898479SChenlu.Chen@Sun.COM DEBUGFUNC("e1000_write_kmrn_reg_80003es2lan");
14908479SChenlu.Chen@Sun.COM
14918479SChenlu.Chen@Sun.COM ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
14928479SChenlu.Chen@Sun.COM if (ret_val)
14938479SChenlu.Chen@Sun.COM goto out;
14948479SChenlu.Chen@Sun.COM
14958479SChenlu.Chen@Sun.COM kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
14968479SChenlu.Chen@Sun.COM E1000_KMRNCTRLSTA_OFFSET) | data;
14978479SChenlu.Chen@Sun.COM E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
14988479SChenlu.Chen@Sun.COM
14998479SChenlu.Chen@Sun.COM usec_delay(2);
15008479SChenlu.Chen@Sun.COM
15018479SChenlu.Chen@Sun.COM e1000_release_mac_csr_80003es2lan(hw);
15028479SChenlu.Chen@Sun.COM
15038479SChenlu.Chen@Sun.COM out:
15048479SChenlu.Chen@Sun.COM return (ret_val);
15058479SChenlu.Chen@Sun.COM }
15068479SChenlu.Chen@Sun.COM
15078479SChenlu.Chen@Sun.COM /*
15086735Scc210113 * e1000_read_mac_addr_80003es2lan - Read device MAC address
15096735Scc210113 * @hw: pointer to the HW structure
15106735Scc210113 */
15116735Scc210113 static s32
e1000_read_mac_addr_80003es2lan(struct e1000_hw * hw)15126735Scc210113 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw)
15136735Scc210113 {
15146735Scc210113 s32 ret_val = E1000_SUCCESS;
15156735Scc210113
15166735Scc210113 DEBUGFUNC("e1000_read_mac_addr_80003es2lan");
151710680SMin.Xu@Sun.COM /*
151810680SMin.Xu@Sun.COM * If there's an alternate MAC address place it in RAR0
151910680SMin.Xu@Sun.COM * so that it will override the Si installed default perm
152010680SMin.Xu@Sun.COM * address.
152110680SMin.Xu@Sun.COM */
152210680SMin.Xu@Sun.COM ret_val = e1000_check_alt_mac_addr_generic(hw);
152310680SMin.Xu@Sun.COM if (ret_val)
152410680SMin.Xu@Sun.COM goto out;
15256735Scc210113
152610680SMin.Xu@Sun.COM ret_val = e1000_read_mac_addr_generic(hw);
152710680SMin.Xu@Sun.COM
152810680SMin.Xu@Sun.COM out:
15296735Scc210113 return (ret_val);
15306735Scc210113 }
15316735Scc210113
15326735Scc210113 /*
15336735Scc210113 * e1000_power_down_phy_copper_80003es2lan - Remove link during PHY power down
15346735Scc210113 * @hw: pointer to the HW structure
15356735Scc210113 *
15366735Scc210113 * In the case of a PHY power down to save power, or to turn off link during a
15376735Scc210113 * driver unload, or wake on lan is not enabled, remove the link.
15386735Scc210113 */
15396735Scc210113 static void
e1000_power_down_phy_copper_80003es2lan(struct e1000_hw * hw)15406735Scc210113 e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw)
15416735Scc210113 {
15426735Scc210113 /* If the management interface is not enabled, then power down */
15436735Scc210113 if (!(hw->mac.ops.check_mng_mode(hw) ||
15446735Scc210113 hw->phy.ops.check_reset_block(hw)))
15456735Scc210113 e1000_power_down_phy_copper(hw);
15466735Scc210113 }
15476735Scc210113
15486735Scc210113 /*
15494919Sxy150489 * e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters
15504919Sxy150489 * @hw: pointer to the HW structure
15514919Sxy150489 *
15524919Sxy150489 * Clears the hardware counters by reading the counter registers.
15534919Sxy150489 */
15544919Sxy150489 static void
e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw * hw)15554919Sxy150489 e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw)
15564919Sxy150489 {
15574919Sxy150489 DEBUGFUNC("e1000_clear_hw_cntrs_80003es2lan");
15584919Sxy150489
15594919Sxy150489 e1000_clear_hw_cntrs_base_generic(hw);
15604919Sxy150489
15617426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_PRC64);
15627426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_PRC127);
15637426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_PRC255);
15647426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_PRC511);
15657426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_PRC1023);
15667426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_PRC1522);
15677426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_PTC64);
15687426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_PTC127);
15697426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_PTC255);
15707426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_PTC511);
15717426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_PTC1023);
15727426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_PTC1522);
15734919Sxy150489
15747426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_ALGNERRC);
15757426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_RXERRC);
15767426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_TNCRS);
15777426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_CEXTERR);
15787426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_TSCTC);
15797426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_TSCTFC);
15804919Sxy150489
15817426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_MGTPRC);
15827426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_MGTPDC);
15837426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_MGTPTC);
15844919Sxy150489
15857426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_IAC);
15867426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_ICRXOC);
15874919Sxy150489
15887426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_ICRXPTC);
15897426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_ICRXATC);
15907426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_ICTXPTC);
15917426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_ICTXATC);
15927426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_ICTXQEC);
15937426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_ICTXQMTC);
15947426SChenliang.Xu@Sun.COM (void) E1000_READ_REG(hw, E1000_ICRXDMTC);
15954919Sxy150489 }
1596