xref: /onnv-gate/usr/src/uts/common/io/e1000g/e1000_mac.c (revision 11387:0072514d53c7)
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.108 v3-1-10-1_2009-9-18_Release14-6
284919Sxy150489  */
294919Sxy150489 #include "e1000_api.h"
304919Sxy150489 
318479SChenlu.Chen@Sun.COM static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw);
3210680SMin.Xu@Sun.COM static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw);
338479SChenlu.Chen@Sun.COM 
344919Sxy150489 /*
356735Scc210113  * e1000_init_mac_ops_generic - Initialize MAC function pointers
366735Scc210113  * @hw: pointer to the HW structure
376735Scc210113  *
386735Scc210113  * Setups up the function pointers to no-op functions
396735Scc210113  */
406735Scc210113 void
e1000_init_mac_ops_generic(struct e1000_hw * hw)416735Scc210113 e1000_init_mac_ops_generic(struct e1000_hw *hw)
426735Scc210113 {
436735Scc210113 	struct e1000_mac_info *mac = &hw->mac;
446735Scc210113 	DEBUGFUNC("e1000_init_mac_ops_generic");
456735Scc210113 
466735Scc210113 	/* General Setup */
476735Scc210113 	mac->ops.init_params = e1000_null_ops_generic;
486735Scc210113 	mac->ops.init_hw = e1000_null_ops_generic;
496735Scc210113 	mac->ops.reset_hw = e1000_null_ops_generic;
506735Scc210113 	mac->ops.setup_physical_interface = e1000_null_ops_generic;
516735Scc210113 	mac->ops.get_bus_info = e1000_null_ops_generic;
5210680SMin.Xu@Sun.COM 	mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pcie;
536735Scc210113 	mac->ops.read_mac_addr = e1000_read_mac_addr_generic;
546735Scc210113 	mac->ops.config_collision_dist = e1000_config_collision_dist_generic;
556735Scc210113 	mac->ops.clear_hw_cntrs = e1000_null_mac_generic;
566735Scc210113 	/* LED */
576735Scc210113 	mac->ops.cleanup_led = e1000_null_ops_generic;
586735Scc210113 	mac->ops.setup_led = e1000_null_ops_generic;
596735Scc210113 	mac->ops.blink_led = e1000_null_ops_generic;
606735Scc210113 	mac->ops.led_on = e1000_null_ops_generic;
616735Scc210113 	mac->ops.led_off = e1000_null_ops_generic;
626735Scc210113 	/* LINK */
636735Scc210113 	mac->ops.setup_link = e1000_null_ops_generic;
646735Scc210113 	mac->ops.get_link_up_info = e1000_null_link_info;
656735Scc210113 	mac->ops.check_for_link = e1000_null_ops_generic;
666735Scc210113 	mac->ops.wait_autoneg = e1000_wait_autoneg_generic;
676735Scc210113 	/* Management */
686735Scc210113 	mac->ops.check_mng_mode = e1000_null_mng_mode;
696735Scc210113 	mac->ops.mng_host_if_write = e1000_mng_host_if_write_generic;
706735Scc210113 	mac->ops.mng_write_cmd_header = e1000_mng_write_cmd_header_generic;
716735Scc210113 	mac->ops.mng_enable_host_if = e1000_mng_enable_host_if_generic;
726735Scc210113 	/* VLAN, MC, etc. */
736735Scc210113 	mac->ops.update_mc_addr_list = e1000_null_update_mc;
746735Scc210113 	mac->ops.clear_vfta = e1000_null_mac_generic;
756735Scc210113 	mac->ops.write_vfta = e1000_null_write_vfta;
766735Scc210113 	mac->ops.mta_set = e1000_null_mta_set;
776735Scc210113 	mac->ops.rar_set = e1000_rar_set_generic;
786735Scc210113 	mac->ops.validate_mdi_setting = e1000_validate_mdi_setting_generic;
796735Scc210113 }
806735Scc210113 
816735Scc210113 /*
826735Scc210113  * e1000_null_ops_generic - No-op function, returns 0
836735Scc210113  * @hw: pointer to the HW structure
846735Scc210113  */
856735Scc210113 s32
e1000_null_ops_generic(struct e1000_hw * hw)866735Scc210113 e1000_null_ops_generic(struct e1000_hw *hw)
876735Scc210113 {
886735Scc210113 	DEBUGFUNC("e1000_null_ops_generic");
896735Scc210113 	UNREFERENCED_1PARAMETER(hw);
906735Scc210113 	return (E1000_SUCCESS);
916735Scc210113 }
926735Scc210113 
936735Scc210113 /*
946735Scc210113  * e1000_null_mac_generic - No-op function, return void
956735Scc210113  * @hw: pointer to the HW structure
966735Scc210113  */
976735Scc210113 void
e1000_null_mac_generic(struct e1000_hw * hw)986735Scc210113 e1000_null_mac_generic(struct e1000_hw *hw)
996735Scc210113 {
1006735Scc210113 	DEBUGFUNC("e1000_null_mac_generic");
1016735Scc210113 	UNREFERENCED_1PARAMETER(hw);
1026735Scc210113 }
1036735Scc210113 
1046735Scc210113 /*
1056735Scc210113  * e1000_null_link_info - No-op function, return 0
1066735Scc210113  * @hw: pointer to the HW structure
1076735Scc210113  */
1086735Scc210113 s32
e1000_null_link_info(struct e1000_hw * hw,u16 * s,u16 * d)1096735Scc210113 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d)
1106735Scc210113 {
1116735Scc210113 	DEBUGFUNC("e1000_null_link_info");
1126735Scc210113 	UNREFERENCED_3PARAMETER(hw, s, d);
1136735Scc210113 	return (E1000_SUCCESS);
1146735Scc210113 }
1156735Scc210113 
1166735Scc210113 /*
1176735Scc210113  * e1000_null_mng_mode - No-op function, return false
1186735Scc210113  * @hw: pointer to the HW structure
1196735Scc210113  */
1206735Scc210113 bool
e1000_null_mng_mode(struct e1000_hw * hw)1216735Scc210113 e1000_null_mng_mode(struct e1000_hw *hw)
1226735Scc210113 {
1236735Scc210113 	DEBUGFUNC("e1000_null_mng_mode");
1246735Scc210113 	UNREFERENCED_1PARAMETER(hw);
1257607STed.You@Sun.COM 	return (false);
1266735Scc210113 }
1276735Scc210113 
1286735Scc210113 /*
1296735Scc210113  * e1000_null_update_mc - No-op function, return void
1306735Scc210113  * @hw: pointer to the HW structure
1316735Scc210113  */
1326735Scc210113 void
e1000_null_update_mc(struct e1000_hw * hw,u8 * h,u32 a)13310680SMin.Xu@Sun.COM e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a)
1346735Scc210113 {
1356735Scc210113 	DEBUGFUNC("e1000_null_update_mc");
13610680SMin.Xu@Sun.COM 	UNREFERENCED_3PARAMETER(hw, h, a);
1376735Scc210113 }
1386735Scc210113 
1396735Scc210113 /*
1406735Scc210113  * e1000_null_write_vfta - No-op function, return void
1416735Scc210113  * @hw: pointer to the HW structure
1426735Scc210113  */
1436735Scc210113 void
e1000_null_write_vfta(struct e1000_hw * hw,u32 a,u32 b)1446735Scc210113 e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b)
1456735Scc210113 {
1466735Scc210113 	DEBUGFUNC("e1000_null_write_vfta");
1476735Scc210113 	UNREFERENCED_3PARAMETER(hw, a, b);
1486735Scc210113 }
1496735Scc210113 
1506735Scc210113 /*
1516735Scc210113  * e1000_null_set_mta - No-op function, return void
1526735Scc210113  * @hw: pointer to the HW structure
1536735Scc210113  */
1546735Scc210113 void
e1000_null_mta_set(struct e1000_hw * hw,u32 a)1556735Scc210113 e1000_null_mta_set(struct e1000_hw *hw, u32 a)
1566735Scc210113 {
1576735Scc210113 	DEBUGFUNC("e1000_null_mta_set");
1586735Scc210113 	UNREFERENCED_2PARAMETER(hw, a);
1596735Scc210113 }
1606735Scc210113 
1616735Scc210113 /*
1626735Scc210113  * e1000_null_rar_set - No-op function, return void
1636735Scc210113  * @hw: pointer to the HW structure
1646735Scc210113  */
1656735Scc210113 void
e1000_null_rar_set(struct e1000_hw * hw,u8 * h,u32 a)1666735Scc210113 e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a)
1676735Scc210113 {
1686735Scc210113 	DEBUGFUNC("e1000_null_rar_set");
1696735Scc210113 	UNREFERENCED_3PARAMETER(hw, h, a);
1706735Scc210113 }
1716735Scc210113 
1726735Scc210113 /*
1734919Sxy150489  * e1000_get_bus_info_pci_generic - Get PCI(x) bus information
1744919Sxy150489  * @hw: pointer to the HW structure
1754919Sxy150489  *
1764919Sxy150489  * Determines and stores the system bus information for a particular
1774919Sxy150489  * network interface.  The following bus information is determined and stored:
1784919Sxy150489  * bus speed, bus width, type (PCI/PCIx), and PCI(-x) function.
1794919Sxy150489  */
1804919Sxy150489 s32
e1000_get_bus_info_pci_generic(struct e1000_hw * hw)1814919Sxy150489 e1000_get_bus_info_pci_generic(struct e1000_hw *hw)
1824919Sxy150489 {
18310680SMin.Xu@Sun.COM 	struct e1000_mac_info *mac = &hw->mac;
1844919Sxy150489 	struct e1000_bus_info *bus = &hw->bus;
1854919Sxy150489 	u32 status = E1000_READ_REG(hw, E1000_STATUS);
1864919Sxy150489 	s32 ret_val = E1000_SUCCESS;
1874919Sxy150489 
1884919Sxy150489 	DEBUGFUNC("e1000_get_bus_info_pci_generic");
1894919Sxy150489 
1904919Sxy150489 	/* PCI or PCI-X? */
1914919Sxy150489 	bus->type = (status & E1000_STATUS_PCIX_MODE)
1924919Sxy150489 	    ? e1000_bus_type_pcix
1934919Sxy150489 	    : e1000_bus_type_pci;
1944919Sxy150489 
1954919Sxy150489 	/* Bus speed */
1964919Sxy150489 	if (bus->type == e1000_bus_type_pci) {
1974919Sxy150489 		bus->speed = (status & E1000_STATUS_PCI66)
1984919Sxy150489 		    ? e1000_bus_speed_66
1994919Sxy150489 		    : e1000_bus_speed_33;
2004919Sxy150489 	} else {
2014919Sxy150489 		switch (status & E1000_STATUS_PCIX_SPEED) {
2024919Sxy150489 		case E1000_STATUS_PCIX_SPEED_66:
2034919Sxy150489 			bus->speed = e1000_bus_speed_66;
2044919Sxy150489 			break;
2054919Sxy150489 		case E1000_STATUS_PCIX_SPEED_100:
2064919Sxy150489 			bus->speed = e1000_bus_speed_100;
2074919Sxy150489 			break;
2084919Sxy150489 		case E1000_STATUS_PCIX_SPEED_133:
2094919Sxy150489 			bus->speed = e1000_bus_speed_133;
2104919Sxy150489 			break;
2114919Sxy150489 		default:
2124919Sxy150489 			bus->speed = e1000_bus_speed_reserved;
2134919Sxy150489 			break;
2144919Sxy150489 		}
2154919Sxy150489 	}
2164919Sxy150489 
2174919Sxy150489 	/* Bus width */
2184919Sxy150489 	bus->width = (status & E1000_STATUS_BUS64)
2194919Sxy150489 	    ? e1000_bus_width_64
2204919Sxy150489 	    : e1000_bus_width_32;
2214919Sxy150489 
2224919Sxy150489 	/* Which PCI(-X) function? */
22310680SMin.Xu@Sun.COM 	mac->ops.set_lan_id(hw);
2244919Sxy150489 
2254919Sxy150489 	return (ret_val);
2264919Sxy150489 }
2274919Sxy150489 
2284919Sxy150489 /*
2294919Sxy150489  * e1000_get_bus_info_pcie_generic - Get PCIe bus information
2304919Sxy150489  * @hw: pointer to the HW structure
2314919Sxy150489  *
2324919Sxy150489  * Determines and stores the system bus information for a particular
2334919Sxy150489  * network interface.  The following bus information is determined and stored:
2344919Sxy150489  * bus speed, bus width, type (PCIe), and PCIe function.
2354919Sxy150489  */
2364919Sxy150489 s32
e1000_get_bus_info_pcie_generic(struct e1000_hw * hw)2374919Sxy150489 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw)
2384919Sxy150489 {
23910680SMin.Xu@Sun.COM 	struct e1000_mac_info *mac = &hw->mac;
2404919Sxy150489 	struct e1000_bus_info *bus = &hw->bus;
2414919Sxy150489 	s32 ret_val;
24210680SMin.Xu@Sun.COM 	u16 pcie_link_status;
2434919Sxy150489 
2444919Sxy150489 	DEBUGFUNC("e1000_get_bus_info_pcie_generic");
2454919Sxy150489 
2464919Sxy150489 	bus->type = e1000_bus_type_pci_express;
2474919Sxy150489 	bus->speed = e1000_bus_speed_2500;
2484919Sxy150489 
2494919Sxy150489 	ret_val = e1000_read_pcie_cap_reg(hw,
2504919Sxy150489 	    PCIE_LINK_STATUS,
2514919Sxy150489 	    &pcie_link_status);
2524919Sxy150489 	if (ret_val)
2534919Sxy150489 		bus->width = e1000_bus_width_unknown;
2544919Sxy150489 	else
2558479SChenlu.Chen@Sun.COM 		bus->width = (enum e1000_bus_width)((pcie_link_status &
2564919Sxy150489 		    PCIE_LINK_WIDTH_MASK) >>
2574919Sxy150489 		    PCIE_LINK_WIDTH_SHIFT);
2584919Sxy150489 
25910680SMin.Xu@Sun.COM 	mac->ops.set_lan_id(hw);
26010680SMin.Xu@Sun.COM 
26110680SMin.Xu@Sun.COM 	return (E1000_SUCCESS);
26210680SMin.Xu@Sun.COM }
26310680SMin.Xu@Sun.COM 
26410680SMin.Xu@Sun.COM /*
26510680SMin.Xu@Sun.COM  * e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
26610680SMin.Xu@Sun.COM  *
26710680SMin.Xu@Sun.COM  * @hw: pointer to the HW structure
26810680SMin.Xu@Sun.COM  *
26910680SMin.Xu@Sun.COM  * Determines the LAN function id by reading memory-mapped registers
27010680SMin.Xu@Sun.COM  * and swaps the port value if requested.
27110680SMin.Xu@Sun.COM  */
27210680SMin.Xu@Sun.COM static void
e1000_set_lan_id_multi_port_pcie(struct e1000_hw * hw)27310680SMin.Xu@Sun.COM e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw)
27410680SMin.Xu@Sun.COM {
27510680SMin.Xu@Sun.COM 	struct e1000_bus_info *bus = &hw->bus;
27610680SMin.Xu@Sun.COM 	u32 reg;
27710680SMin.Xu@Sun.COM 
27810680SMin.Xu@Sun.COM 	/*
27910680SMin.Xu@Sun.COM 	 * The status register reports the correct function number
28010680SMin.Xu@Sun.COM 	 * for the device regardless of function swap state.
28110680SMin.Xu@Sun.COM 	 */
28210680SMin.Xu@Sun.COM 	reg = E1000_READ_REG(hw, E1000_STATUS);
28310680SMin.Xu@Sun.COM 	bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT;
28410680SMin.Xu@Sun.COM }
28510680SMin.Xu@Sun.COM 
28610680SMin.Xu@Sun.COM /*
28710680SMin.Xu@Sun.COM  * e1000_set_lan_id_multi_port_pci - Set LAN id for PCI multiple port devices
28810680SMin.Xu@Sun.COM  * @hw: pointer to the HW structure
28910680SMin.Xu@Sun.COM  *
29010680SMin.Xu@Sun.COM  * Determines the LAN function id by reading PCI config space.
29110680SMin.Xu@Sun.COM  */
29210680SMin.Xu@Sun.COM void
e1000_set_lan_id_multi_port_pci(struct e1000_hw * hw)29310680SMin.Xu@Sun.COM e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw)
29410680SMin.Xu@Sun.COM {
29510680SMin.Xu@Sun.COM 	struct e1000_bus_info *bus = &hw->bus;
29610680SMin.Xu@Sun.COM 	u16 pci_header_type;
29710680SMin.Xu@Sun.COM 	u32 status;
29810680SMin.Xu@Sun.COM 
2994919Sxy150489 	e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type);
3004919Sxy150489 	if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) {
3014919Sxy150489 		status = E1000_READ_REG(hw, E1000_STATUS);
3024919Sxy150489 		bus->func = (status & E1000_STATUS_FUNC_MASK)
3034919Sxy150489 		    >> E1000_STATUS_FUNC_SHIFT;
3044919Sxy150489 	} else {
3054919Sxy150489 		bus->func = 0;
3064919Sxy150489 	}
30710680SMin.Xu@Sun.COM }
3084919Sxy150489 
30910680SMin.Xu@Sun.COM /*
31010680SMin.Xu@Sun.COM  * e1000_set_lan_id_single_port - Set LAN id for a single port device
31110680SMin.Xu@Sun.COM  * @hw: pointer to the HW structure
31210680SMin.Xu@Sun.COM  *
31310680SMin.Xu@Sun.COM  * Sets the LAN function id to zero for a single port device.
31410680SMin.Xu@Sun.COM  */
31510680SMin.Xu@Sun.COM void
e1000_set_lan_id_single_port(struct e1000_hw * hw)31610680SMin.Xu@Sun.COM e1000_set_lan_id_single_port(struct e1000_hw *hw)
31710680SMin.Xu@Sun.COM {
31810680SMin.Xu@Sun.COM 	struct e1000_bus_info *bus = &hw->bus;
31910680SMin.Xu@Sun.COM 
32010680SMin.Xu@Sun.COM 	bus->func = 0;
3214919Sxy150489 }
3224919Sxy150489 
3234919Sxy150489 /*
3244919Sxy150489  * e1000_clear_vfta_generic - Clear VLAN filter table
3254919Sxy150489  * @hw: pointer to the HW structure
3264919Sxy150489  *
3274919Sxy150489  * Clears the register array which contains the VLAN filter table by
3284919Sxy150489  * setting all the values to 0.
3294919Sxy150489  */
3304919Sxy150489 void
e1000_clear_vfta_generic(struct e1000_hw * hw)3314919Sxy150489 e1000_clear_vfta_generic(struct e1000_hw *hw)
3324919Sxy150489 {
3334919Sxy150489 	u32 offset;
3344919Sxy150489 
3354919Sxy150489 	DEBUGFUNC("e1000_clear_vfta_generic");
3364919Sxy150489 
3374919Sxy150489 	for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
3384919Sxy150489 		E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0);
3394919Sxy150489 		E1000_WRITE_FLUSH(hw);
3404919Sxy150489 	}
3414919Sxy150489 }
3424919Sxy150489 
3434919Sxy150489 /*
3444919Sxy150489  * e1000_write_vfta_generic - Write value to VLAN filter table
3454919Sxy150489  * @hw: pointer to the HW structure
3464919Sxy150489  * @offset: register offset in VLAN filter table
3474919Sxy150489  * @value: register value written to VLAN filter table
3484919Sxy150489  *
3494919Sxy150489  * Writes value at the given offset in the register array which stores
3504919Sxy150489  * the VLAN filter table.
3514919Sxy150489  */
3524919Sxy150489 void
e1000_write_vfta_generic(struct e1000_hw * hw,u32 offset,u32 value)3534919Sxy150489 e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value)
3544919Sxy150489 {
3554919Sxy150489 	DEBUGFUNC("e1000_write_vfta_generic");
3564919Sxy150489 
3574919Sxy150489 	E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
3584919Sxy150489 	E1000_WRITE_FLUSH(hw);
3594919Sxy150489 }
3604919Sxy150489 
3614919Sxy150489 /*
3624919Sxy150489  * e1000_init_rx_addrs_generic - Initialize receive address's
3634919Sxy150489  * @hw: pointer to the HW structure
3644919Sxy150489  * @rar_count: receive address registers
3654919Sxy150489  *
3664919Sxy150489  * Setups the receive address registers by setting the base receive address
3674919Sxy150489  * register to the devices MAC address and clearing all the other receive
3684919Sxy150489  * address registers to 0.
3694919Sxy150489  */
3704919Sxy150489 void
e1000_init_rx_addrs_generic(struct e1000_hw * hw,u16 rar_count)3714919Sxy150489 e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count)
3724919Sxy150489 {
3734919Sxy150489 	u32 i;
37410680SMin.Xu@Sun.COM 	u8 mac_addr[ETH_ADDR_LEN] = {0};
3754919Sxy150489 
3764919Sxy150489 	DEBUGFUNC("e1000_init_rx_addrs_generic");
3774919Sxy150489 
3784919Sxy150489 	/* Setup the receive address */
3794919Sxy150489 	DEBUGOUT("Programming MAC Address into RAR[0]\n");
3804919Sxy150489 
3817607STed.You@Sun.COM 	hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
3824919Sxy150489 
3834919Sxy150489 	/* Zero out the other (rar_entry_count - 1) receive addresses */
3844919Sxy150489 	DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count - 1);
38510680SMin.Xu@Sun.COM 	for (i = 1; i < rar_count; i++)
38610680SMin.Xu@Sun.COM 		hw->mac.ops.rar_set(hw, mac_addr, i);
38710680SMin.Xu@Sun.COM 
3884919Sxy150489 }
3894919Sxy150489 
3904919Sxy150489 /*
3916735Scc210113  * e1000_check_alt_mac_addr_generic - Check for alternate MAC addr
3926735Scc210113  * @hw: pointer to the HW structure
3936735Scc210113  *
3946735Scc210113  * Checks the nvm for an alternate MAC address.  An alternate MAC address
3956735Scc210113  * can be setup by pre-boot software and must be treated like a permanent
3966735Scc210113  * address and must override the actual permanent MAC address.  If an
39710680SMin.Xu@Sun.COM  * alternate MAC address is found it is programmed into RAR0, replacing
39810680SMin.Xu@Sun.COM  * the permanent address that was installed into RAR0 by the Si on reset.
39910680SMin.Xu@Sun.COM  * This function will return SUCCESS unless it encounters an error while
40010680SMin.Xu@Sun.COM  * reading the EEPROM.
4016735Scc210113  */
4026735Scc210113 s32
e1000_check_alt_mac_addr_generic(struct e1000_hw * hw)4036735Scc210113 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
4046735Scc210113 {
4056735Scc210113 	u32 i;
4066735Scc210113 	s32 ret_val = E1000_SUCCESS;
4076735Scc210113 	u16 offset, nvm_alt_mac_addr_offset, nvm_data;
4086735Scc210113 	u8 alt_mac_addr[ETH_ADDR_LEN];
4096735Scc210113 
4106735Scc210113 	DEBUGFUNC("e1000_check_alt_mac_addr_generic");
4116735Scc210113 
4126735Scc210113 	ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1,
4136735Scc210113 	    &nvm_alt_mac_addr_offset);
4146735Scc210113 	if (ret_val) {
4156735Scc210113 		DEBUGOUT("NVM Read Error\n");
4166735Scc210113 		goto out;
4176735Scc210113 	}
4186735Scc210113 
4196735Scc210113 	if (nvm_alt_mac_addr_offset == 0xFFFF) {
42010680SMin.Xu@Sun.COM 		/* There is no Alternate MAC Address */
4216735Scc210113 		goto out;
4226735Scc210113 	}
4236735Scc210113 
4246735Scc210113 	if (hw->bus.func == E1000_FUNC_1)
42510680SMin.Xu@Sun.COM 		nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
4266735Scc210113 
4276735Scc210113 	for (i = 0; i < ETH_ADDR_LEN; i += 2) {
4286735Scc210113 		offset = nvm_alt_mac_addr_offset + (i >> 1);
4296735Scc210113 		ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
4306735Scc210113 		if (ret_val) {
4316735Scc210113 			DEBUGOUT("NVM Read Error\n");
4326735Scc210113 			goto out;
4336735Scc210113 		}
4346735Scc210113 
4356735Scc210113 		alt_mac_addr[i] = (u8)(nvm_data & 0xFF);
4366735Scc210113 		alt_mac_addr[i + 1] = (u8)(nvm_data >> 8);
4376735Scc210113 	}
4386735Scc210113 
4396735Scc210113 	/* if multicast bit is set, the alternate address will not be used */
4406735Scc210113 	if (alt_mac_addr[0] & 0x01) {
44110680SMin.Xu@Sun.COM 		DEBUGOUT("Ignoring Alternate Mac Address with MC bit set\n");
4426735Scc210113 		goto out;
4436735Scc210113 	}
4446735Scc210113 
44510680SMin.Xu@Sun.COM 	/*
44610680SMin.Xu@Sun.COM 	 * We have a valid alternate MAC address, and we want to treat it the
44710680SMin.Xu@Sun.COM 	 * same as the normal permanent MAC address stored by the HW into the
44810680SMin.Xu@Sun.COM 	 * RAR. Do this by mapping this address into RAR0.
44910680SMin.Xu@Sun.COM 	 */
45010680SMin.Xu@Sun.COM 	hw->mac.ops.rar_set(hw, alt_mac_addr, 0);
4516735Scc210113 
4526735Scc210113 out:
4536735Scc210113 	return (ret_val);
4546735Scc210113 }
4556735Scc210113 
4566735Scc210113 /*
4574919Sxy150489  * e1000_rar_set_generic - Set receive address register
4584919Sxy150489  * @hw: pointer to the HW structure
4594919Sxy150489  * @addr: pointer to the receive address
4604919Sxy150489  * @index: receive address array register
4614919Sxy150489  *
4624919Sxy150489  * Sets the receive address array register at index to the address passed
4634919Sxy150489  * in by addr.
4644919Sxy150489  */
4654919Sxy150489 void
e1000_rar_set_generic(struct e1000_hw * hw,u8 * addr,u32 index)4664919Sxy150489 e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
4674919Sxy150489 {
4684919Sxy150489 	u32 rar_low, rar_high;
4694919Sxy150489 
4704919Sxy150489 	DEBUGFUNC("e1000_rar_set_generic");
4714919Sxy150489 
4724919Sxy150489 	/*
4734919Sxy150489 	 * HW expects these in little endian so we reverse the byte order from
4744919Sxy150489 	 * network order (big endian) to little endian
4754919Sxy150489 	 */
4764919Sxy150489 	rar_low = ((u32) addr[0] |
4774919Sxy150489 	    ((u32) addr[1] << 8) |
4784919Sxy150489 	    ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
4794919Sxy150489 
4804919Sxy150489 	rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
4814919Sxy150489 
4826735Scc210113 	/* If MAC address zero, no need to set the AV bit */
4838479SChenlu.Chen@Sun.COM 	if (rar_low || rar_high)
4848479SChenlu.Chen@Sun.COM 		rar_high |= E1000_RAH_AV;
4854919Sxy150489 
4868178SChenlu.Chen@Sun.COM 	/*
4878178SChenlu.Chen@Sun.COM 	 * Some bridges will combine consecutive 32-bit writes into
48810680SMin.Xu@Sun.COM 	 * a single burst write, which will malfunction on some parts.
48910680SMin.Xu@Sun.COM 	 * The flushes avoid this.
4908178SChenlu.Chen@Sun.COM 	 */
4916735Scc210113 	E1000_WRITE_REG(hw, E1000_RAL(index), rar_low);
4928178SChenlu.Chen@Sun.COM 	E1000_WRITE_FLUSH(hw);
4936735Scc210113 	E1000_WRITE_REG(hw, E1000_RAH(index), rar_high);
49410680SMin.Xu@Sun.COM 	E1000_WRITE_FLUSH(hw);
4954919Sxy150489 }
4964919Sxy150489 
4974919Sxy150489 /*
4984919Sxy150489  * e1000_mta_set_generic - Set multicast filter table address
4994919Sxy150489  * @hw: pointer to the HW structure
5004919Sxy150489  * @hash_value: determines the MTA register and bit to set
5014919Sxy150489  *
5024919Sxy150489  * The multicast table address is a register array of 32-bit registers.
5034919Sxy150489  * The hash_value is used to determine what register the bit is in, the
5044919Sxy150489  * current value is read, the new bit is OR'd in and the new value is
5054919Sxy150489  * written back into the register.
5064919Sxy150489  */
5074919Sxy150489 void
e1000_mta_set_generic(struct e1000_hw * hw,u32 hash_value)5084919Sxy150489 e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value)
5094919Sxy150489 {
5104919Sxy150489 	u32 hash_bit, hash_reg, mta;
5114919Sxy150489 
5124919Sxy150489 	DEBUGFUNC("e1000_mta_set_generic");
5134919Sxy150489 	/*
5144919Sxy150489 	 * The MTA is a register array of 32-bit registers. It is treated like
5154919Sxy150489 	 * an array of (32*mta_reg_count) bits.  We want to set bit
5164919Sxy150489 	 * BitArray[hash_value]. So we figure out what register the bit is in,
5174919Sxy150489 	 * read it, OR in the new bit, then write back the new value.  The
5184919Sxy150489 	 * (hw->mac.mta_reg_count - 1) serves as a mask to bits 31:5 of the
5194919Sxy150489 	 * hash value which gives us the register we're modifying.  The hash
5204919Sxy150489 	 * bit within that register is determined by the lower 5 bits of the
5214919Sxy150489 	 * hash value.
5224919Sxy150489 	 */
5234919Sxy150489 	hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
5244919Sxy150489 	hash_bit = hash_value & 0x1F;
5254919Sxy150489 
5264919Sxy150489 	mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg);
5274919Sxy150489 
5284919Sxy150489 	mta |= (1 << hash_bit);
5294919Sxy150489 
5304919Sxy150489 	E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta);
5314919Sxy150489 	E1000_WRITE_FLUSH(hw);
5324919Sxy150489 }
5334919Sxy150489 
5344919Sxy150489 /*
5356735Scc210113  * e1000_update_mc_addr_list_generic - Update Multicast addresses
5364919Sxy150489  * @hw: pointer to the HW structure
5374919Sxy150489  * @mc_addr_list: array of multicast addresses to program
5384919Sxy150489  * @mc_addr_count: number of multicast addresses to program
5394919Sxy150489  *
54010680SMin.Xu@Sun.COM  * Updates entire Multicast Table Array.
5414919Sxy150489  * The caller must have a packed mc_addr_list of multicast addresses.
5424919Sxy150489  */
5434919Sxy150489 void
e1000_update_mc_addr_list_generic(struct e1000_hw * hw,u8 * mc_addr_list,u32 mc_addr_count)5446735Scc210113 e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
54510680SMin.Xu@Sun.COM     u8 *mc_addr_list, u32 mc_addr_count)
5464919Sxy150489 {
54710680SMin.Xu@Sun.COM 	u32 hash_value, hash_bit, hash_reg;
54810680SMin.Xu@Sun.COM 	int i;
5494919Sxy150489 
5506735Scc210113 	DEBUGFUNC("e1000_update_mc_addr_list_generic");
5514919Sxy150489 
55210680SMin.Xu@Sun.COM 	/* clear mta_shadow */
553*11387SSurya.Prakki@Sun.COM 	(void) memset(&hw->mac.mta_shadow, 0, sizeof (hw->mac.mta_shadow));
55410680SMin.Xu@Sun.COM 
55510680SMin.Xu@Sun.COM 	/* update mta_shadow from mc_addr_list */
55610680SMin.Xu@Sun.COM 	for (i = 0; (u32) i < mc_addr_count; i++) {
55710680SMin.Xu@Sun.COM 		hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list);
55810680SMin.Xu@Sun.COM 
55910680SMin.Xu@Sun.COM 		hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
56010680SMin.Xu@Sun.COM 		hash_bit = hash_value & 0x1F;
56110680SMin.Xu@Sun.COM 
56210680SMin.Xu@Sun.COM 		hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
56310680SMin.Xu@Sun.COM 		mc_addr_list += (ETH_ADDR_LEN);
5644919Sxy150489 	}
5654919Sxy150489 
56610680SMin.Xu@Sun.COM 	/* replace the entire MTA table */
56710680SMin.Xu@Sun.COM 	for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
56810680SMin.Xu@Sun.COM 		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]);
56910680SMin.Xu@Sun.COM 	E1000_WRITE_FLUSH(hw);
5704919Sxy150489 }
5714919Sxy150489 
5724919Sxy150489 /*
5734919Sxy150489  * e1000_hash_mc_addr_generic - Generate a multicast hash value
5744919Sxy150489  * @hw: pointer to the HW structure
5754919Sxy150489  * @mc_addr: pointer to a multicast address
5764919Sxy150489  *
5774919Sxy150489  * Generates a multicast address hash value which is used to determine
5784919Sxy150489  * the multicast filter table array address and new table value.  See
5794919Sxy150489  * e1000_mta_set_generic()
5804919Sxy150489  */
5814919Sxy150489 u32
e1000_hash_mc_addr_generic(struct e1000_hw * hw,u8 * mc_addr)5824919Sxy150489 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr)
5834919Sxy150489 {
5844919Sxy150489 	u32 hash_value, hash_mask;
5854919Sxy150489 	u8 bit_shift = 0;
5864919Sxy150489 
5874919Sxy150489 	DEBUGFUNC("e1000_hash_mc_addr_generic");
5884919Sxy150489 
5894919Sxy150489 	/* Register count multiplied by bits per register */
5904919Sxy150489 	hash_mask = (hw->mac.mta_reg_count * 32) - 1;
5914919Sxy150489 
5924919Sxy150489 	/*
5934919Sxy150489 	 * For a mc_filter_type of 0, bit_shift is the number of left-shifts
5944919Sxy150489 	 * where 0xFF would still fall within the hash mask.
5954919Sxy150489 	 */
5964919Sxy150489 	while (hash_mask >> bit_shift != 0xFF)
5974919Sxy150489 		bit_shift++;
5984919Sxy150489 
5994919Sxy150489 	/*
6004919Sxy150489 	 * The portion of the address that is used for the hash table is
6014919Sxy150489 	 * determined by the mc_filter_type setting. The algorithm is such
6024919Sxy150489 	 * that there is a total of 8 bits of shifting. The bit_shift for a
6034919Sxy150489 	 * mc_filter_type of 0 represents the number of left-shifts where the
6044919Sxy150489 	 * MSB of mc_addr[5] would still fall within the hash_mask.  Case 0
6054919Sxy150489 	 * does this exactly.  Since there are a total of 8 bits of shifting,
6064919Sxy150489 	 * then mc_addr[4] will shift right the remaining number of bits. Thus
6074919Sxy150489 	 * 8 - bit_shift.  The rest of the cases are a variation of this
6084919Sxy150489 	 * algorithm...essentially raising the number of bits to shift
6094919Sxy150489 	 * mc_addr[5] left, while still keeping the 8-bit shifting total.
6104919Sxy150489 	 *
6114919Sxy150489 	 * For example, given the following Destination MAC Address and an mta
6124919Sxy150489 	 * register count of 128 (thus a 4096-bit vector and 0xFFF mask), we
6134919Sxy150489 	 * can see that the bit_shift for case 0 is 4.  These are the hash
6144919Sxy150489 	 * values resulting from each mc_filter_type...
6154919Sxy150489 	 * [0] [1] [2] [3] [4] [5]
6164919Sxy150489 	 * 01  AA  00  12  34  56
6174919Sxy150489 	 * LSB			MSB
6184919Sxy150489 	 *
6194919Sxy150489 	 * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563
6204919Sxy150489 	 * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6
6214919Sxy150489 	 * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163
6224919Sxy150489 	 * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634
6234919Sxy150489 	 */
6244919Sxy150489 	switch (hw->mac.mc_filter_type) {
6254919Sxy150489 	default:
6264919Sxy150489 	case 0:
6274919Sxy150489 		break;
6284919Sxy150489 	case 1:
6294919Sxy150489 		bit_shift += 1;
6304919Sxy150489 		break;
6314919Sxy150489 	case 2:
6324919Sxy150489 		bit_shift += 2;
6334919Sxy150489 		break;
6344919Sxy150489 	case 3:
6354919Sxy150489 		bit_shift += 4;
6364919Sxy150489 		break;
6374919Sxy150489 	}
6384919Sxy150489 
6394919Sxy150489 	hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
6404919Sxy150489 	    (((u16) mc_addr[5]) << bit_shift)));
6414919Sxy150489 
6424919Sxy150489 	return (hash_value);
6434919Sxy150489 }
6444919Sxy150489 
6454919Sxy150489 /*
6464919Sxy150489  * e1000_pcix_mmrbc_workaround_generic - Fix incorrect MMRBC value
6474919Sxy150489  * @hw: pointer to the HW structure
6484919Sxy150489  *
6494919Sxy150489  * In certain situations, a system BIOS may report that the PCIx maximum
6504919Sxy150489  * memory read byte count (MMRBC) value is higher than than the actual
6516735Scc210113  * value. We check the PCIx command register with the current PCIx status
6526735Scc210113  * register.
6534919Sxy150489  */
6544919Sxy150489 void
e1000_pcix_mmrbc_workaround_generic(struct e1000_hw * hw)6554919Sxy150489 e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw)
6564919Sxy150489 {
6574919Sxy150489 	u16 cmd_mmrbc;
6584919Sxy150489 	u16 pcix_cmd;
6594919Sxy150489 	u16 pcix_stat_hi_word;
6604919Sxy150489 	u16 stat_mmrbc;
6614919Sxy150489 
6624919Sxy150489 	DEBUGFUNC("e1000_pcix_mmrbc_workaround_generic");
6634919Sxy150489 
6644919Sxy150489 	/* Workaround for PCI-X issue when BIOS sets MMRBC incorrectly */
6654919Sxy150489 	if (hw->bus.type != e1000_bus_type_pcix)
6664919Sxy150489 		return;
6674919Sxy150489 
6684919Sxy150489 	e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd);
6694919Sxy150489 	e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word);
6704919Sxy150489 	cmd_mmrbc = (pcix_cmd & PCIX_COMMAND_MMRBC_MASK) >>
6714919Sxy150489 	    PCIX_COMMAND_MMRBC_SHIFT;
6724919Sxy150489 	stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >>
6734919Sxy150489 	    PCIX_STATUS_HI_MMRBC_SHIFT;
6744919Sxy150489 	if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K)
6754919Sxy150489 		stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K;
6764919Sxy150489 	if (cmd_mmrbc > stat_mmrbc) {
6774919Sxy150489 		pcix_cmd &= ~PCIX_COMMAND_MMRBC_MASK;
6784919Sxy150489 		pcix_cmd |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT;
6794919Sxy150489 		e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd);
6804919Sxy150489 	}
6814919Sxy150489 }
6824919Sxy150489 
6834919Sxy150489 /*
6844919Sxy150489  * e1000_clear_hw_cntrs_base_generic - Clear base hardware counters
6854919Sxy150489  * @hw: pointer to the HW structure
6864919Sxy150489  *
6874919Sxy150489  * Clears the base hardware counters by reading the counter registers.
6884919Sxy150489  */
6894919Sxy150489 void
e1000_clear_hw_cntrs_base_generic(struct e1000_hw * hw)6904919Sxy150489 e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw)
6914919Sxy150489 {
6924919Sxy150489 	DEBUGFUNC("e1000_clear_hw_cntrs_base_generic");
6934919Sxy150489 
6947426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_CRCERRS);
6957426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_SYMERRS);
6967426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_MPC);
6977426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_SCC);
6987426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_ECOL);
6997426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_MCC);
7007426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_LATECOL);
7017426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_COLC);
7027426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_DC);
7037426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_SEC);
7047426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_RLEC);
7057426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_XONRXC);
7067426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_XONTXC);
7077426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_XOFFRXC);
7087426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_XOFFTXC);
7097426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_FCRUC);
7107426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_GPRC);
7117426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_BPRC);
7127426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_MPRC);
7137426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_GPTC);
7147426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_GORCL);
7157426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_GORCH);
7167426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_GOTCL);
7177426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_GOTCH);
7187426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_RNBC);
7197426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_RUC);
7207426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_RFC);
7217426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_ROC);
7227426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_RJC);
7237426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_TORL);
7247426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_TORH);
7257426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_TOTL);
7267426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_TOTH);
7277426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_TPR);
7287426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_TPT);
7297426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_MPTC);
7307426SChenliang.Xu@Sun.COM 	(void) E1000_READ_REG(hw, E1000_BPTC);
7314919Sxy150489 }
7324919Sxy150489 
7334919Sxy150489 /*
7344919Sxy150489  * e1000_check_for_copper_link_generic - Check for link (Copper)
7354919Sxy150489  * @hw: pointer to the HW structure
7364919Sxy150489  *
7374919Sxy150489  * Checks to see of the link status of the hardware has changed.  If a
7384919Sxy150489  * change in link status has been detected, then we read the PHY registers
7394919Sxy150489  * to get the current speed/duplex if link exists.
7404919Sxy150489  */
7414919Sxy150489 s32
e1000_check_for_copper_link_generic(struct e1000_hw * hw)7424919Sxy150489 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
7434919Sxy150489 {
7444919Sxy150489 	struct e1000_mac_info *mac = &hw->mac;
7454919Sxy150489 	s32 ret_val;
7466735Scc210113 	bool link;
7474919Sxy150489 
7484919Sxy150489 	DEBUGFUNC("e1000_check_for_copper_link");
7494919Sxy150489 
7504919Sxy150489 	/*
7514919Sxy150489 	 * We only want to go out to the PHY registers to see if Auto-Neg has
7524919Sxy150489 	 * completed and/or if our link status has changed.  The
7534919Sxy150489 	 * get_link_status flag is set upon receiving a Link Status Change or
7544919Sxy150489 	 * Rx Sequence Error interrupt.
7554919Sxy150489 	 */
7564919Sxy150489 	if (!mac->get_link_status) {
7574919Sxy150489 		ret_val = E1000_SUCCESS;
7584919Sxy150489 		goto out;
7594919Sxy150489 	}
7604919Sxy150489 
7614919Sxy150489 	/*
7624919Sxy150489 	 * First we want to see if the MII Status Register reports link.  If
7634919Sxy150489 	 * so, then we want to get the current speed/duplex of the PHY.
7644919Sxy150489 	 */
7654919Sxy150489 	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
7664919Sxy150489 	if (ret_val)
7674919Sxy150489 		goto out;
7684919Sxy150489 
7694919Sxy150489 	if (!link)
7704919Sxy150489 		goto out;	/* No link detected */
7714919Sxy150489 
7727607STed.You@Sun.COM 	mac->get_link_status = false;
7734919Sxy150489 
7744919Sxy150489 	/*
7754919Sxy150489 	 * Check if there was DownShift, must be checked immediately after
7764919Sxy150489 	 * link-up
7774919Sxy150489 	 */
7787426SChenliang.Xu@Sun.COM 	(void) e1000_check_downshift_generic(hw);
7794919Sxy150489 
7804919Sxy150489 	/*
7814919Sxy150489 	 * If we are forcing speed/duplex, then we simply return since we have
7824919Sxy150489 	 * already determined whether we have link or not.
7834919Sxy150489 	 */
7844919Sxy150489 	if (!mac->autoneg) {
7854919Sxy150489 		ret_val = -E1000_ERR_CONFIG;
7864919Sxy150489 		goto out;
7874919Sxy150489 	}
7884919Sxy150489 
7894919Sxy150489 	/*
7904919Sxy150489 	 * Auto-Neg is enabled.  Auto Speed Detection takes care of MAC
7914919Sxy150489 	 * speed/duplex configuration.  So we only need to configure Collision
7924919Sxy150489 	 * Distance in the MAC.
7934919Sxy150489 	 */
7944919Sxy150489 	e1000_config_collision_dist_generic(hw);
7954919Sxy150489 
7964919Sxy150489 	/*
7974919Sxy150489 	 * Configure Flow Control now that Auto-Neg has completed. First, we
7984919Sxy150489 	 * need to restore the desired flow control settings because we may
7994919Sxy150489 	 * have had to re-autoneg with a different link partner.
8004919Sxy150489 	 */
8014919Sxy150489 	ret_val = e1000_config_fc_after_link_up_generic(hw);
80211143SGuoqing.Zhu@Sun.COM 	if (ret_val) {
80311143SGuoqing.Zhu@Sun.COM 		/* EMPTY */
8044919Sxy150489 		DEBUGOUT("Error configuring flow control\n");
80511143SGuoqing.Zhu@Sun.COM 	}
8064919Sxy150489 
8074919Sxy150489 out:
8084919Sxy150489 	return (ret_val);
8094919Sxy150489 }
8104919Sxy150489 
8114919Sxy150489 /*
8124919Sxy150489  * e1000_check_for_fiber_link_generic - Check for link (Fiber)
8134919Sxy150489  * @hw: pointer to the HW structure
8144919Sxy150489  *
8154919Sxy150489  * Checks for link up on the hardware.  If link is not up and we have
8164919Sxy150489  * a signal, then we need to force link up.
8174919Sxy150489  */
8184919Sxy150489 s32
e1000_check_for_fiber_link_generic(struct e1000_hw * hw)8194919Sxy150489 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
8204919Sxy150489 {
8214919Sxy150489 	struct e1000_mac_info *mac = &hw->mac;
8224919Sxy150489 	u32 rxcw;
8234919Sxy150489 	u32 ctrl;
8244919Sxy150489 	u32 status;
8254919Sxy150489 	s32 ret_val = E1000_SUCCESS;
8264919Sxy150489 
8274919Sxy150489 	DEBUGFUNC("e1000_check_for_fiber_link_generic");
8284919Sxy150489 
8294919Sxy150489 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
8304919Sxy150489 	status = E1000_READ_REG(hw, E1000_STATUS);
8314919Sxy150489 	rxcw = E1000_READ_REG(hw, E1000_RXCW);
8324919Sxy150489 
8334919Sxy150489 	/*
8344919Sxy150489 	 * If we don't have link (auto-negotiation failed or link partner
8354919Sxy150489 	 * cannot auto-negotiate), the cable is plugged in (we have signal),
8364919Sxy150489 	 * and our link partner is not trying to auto-negotiate with us (we
8374919Sxy150489 	 * are receiving idles or data), we need to force link up. We also
8384919Sxy150489 	 * need to give auto-negotiation time to complete, in case the cable
8394919Sxy150489 	 * was just plugged in. The autoneg_failed flag does this.
8404919Sxy150489 	 */
8414919Sxy150489 	/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
8424919Sxy150489 	if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) &&
8434919Sxy150489 	    (!(rxcw & E1000_RXCW_C))) {
8444919Sxy150489 		if (mac->autoneg_failed == 0) {
8454919Sxy150489 			mac->autoneg_failed = 1;
8464919Sxy150489 			goto out;
8474919Sxy150489 		}
8484919Sxy150489 		DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
8494919Sxy150489 
8504919Sxy150489 		/* Disable auto-negotiation in the TXCW register */
8514919Sxy150489 		E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));
8524919Sxy150489 
8534919Sxy150489 		/* Force link-up and also force full-duplex. */
8544919Sxy150489 		ctrl = E1000_READ_REG(hw, E1000_CTRL);
8554919Sxy150489 		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
8564919Sxy150489 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
8574919Sxy150489 
8584919Sxy150489 		/* Configure Flow Control after forcing link up. */
8594919Sxy150489 		ret_val = e1000_config_fc_after_link_up_generic(hw);
8604919Sxy150489 		if (ret_val) {
8614919Sxy150489 			DEBUGOUT("Error configuring flow control\n");
8624919Sxy150489 			goto out;
8634919Sxy150489 		}
8644919Sxy150489 	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
8654919Sxy150489 		/*
8664919Sxy150489 		 * If we are forcing link and we are receiving /C/ ordered
8674919Sxy150489 		 * sets, re-enable auto-negotiation in the TXCW register and
8684919Sxy150489 		 * disable forced link in the Device Control register in an
8694919Sxy150489 		 * attempt to auto-negotiate with our link partner.
8704919Sxy150489 		 */
8714919Sxy150489 		DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
8724919Sxy150489 		E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
8734919Sxy150489 		E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));
8744919Sxy150489 
8757607STed.You@Sun.COM 		mac->serdes_has_link = true;
8764919Sxy150489 	}
8774919Sxy150489 
8784919Sxy150489 out:
8794919Sxy150489 	return (ret_val);
8804919Sxy150489 }
8814919Sxy150489 
8824919Sxy150489 /*
8834919Sxy150489  * e1000_check_for_serdes_link_generic - Check for link (Serdes)
8844919Sxy150489  * @hw: pointer to the HW structure
8854919Sxy150489  *
8864919Sxy150489  * Checks for link up on the hardware.  If link is not up and we have
8874919Sxy150489  * a signal, then we need to force link up.
8884919Sxy150489  */
8894919Sxy150489 s32
e1000_check_for_serdes_link_generic(struct e1000_hw * hw)8904919Sxy150489 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
8914919Sxy150489 {
8924919Sxy150489 	struct e1000_mac_info *mac = &hw->mac;
8934919Sxy150489 	u32 rxcw;
8944919Sxy150489 	u32 ctrl;
8954919Sxy150489 	u32 status;
8964919Sxy150489 	s32 ret_val = E1000_SUCCESS;
8974919Sxy150489 
8984919Sxy150489 	DEBUGFUNC("e1000_check_for_serdes_link_generic");
8994919Sxy150489 
9004919Sxy150489 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
9014919Sxy150489 	status = E1000_READ_REG(hw, E1000_STATUS);
9024919Sxy150489 	rxcw = E1000_READ_REG(hw, E1000_RXCW);
9034919Sxy150489 
9044919Sxy150489 	/*
9054919Sxy150489 	 * If we don't have link (auto-negotiation failed or link partner
9064919Sxy150489 	 * cannot auto-negotiate), and our link partner is not trying to
9074919Sxy150489 	 * auto-negotiate with us (we are receiving idles or data), we need to
9084919Sxy150489 	 * force link up. We also need to give auto-negotiation time to
9094919Sxy150489 	 * complete.
9104919Sxy150489 	 */
9114919Sxy150489 	/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
9124919Sxy150489 	if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
9134919Sxy150489 		if (mac->autoneg_failed == 0) {
9144919Sxy150489 			mac->autoneg_failed = 1;
9154919Sxy150489 			goto out;
9164919Sxy150489 		}
9174919Sxy150489 		DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
9184919Sxy150489 
9194919Sxy150489 		/* Disable auto-negotiation in the TXCW register */
9204919Sxy150489 		E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));
9214919Sxy150489 
9224919Sxy150489 		/* Force link-up and also force full-duplex. */
9234919Sxy150489 		ctrl = E1000_READ_REG(hw, E1000_CTRL);
9244919Sxy150489 		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
9254919Sxy150489 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
9264919Sxy150489 
9274919Sxy150489 		/* Configure Flow Control after forcing link up. */
9284919Sxy150489 		ret_val = e1000_config_fc_after_link_up_generic(hw);
9294919Sxy150489 		if (ret_val) {
9304919Sxy150489 			DEBUGOUT("Error configuring flow control\n");
9314919Sxy150489 			goto out;
9324919Sxy150489 		}
9334919Sxy150489 	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
9344919Sxy150489 		/*
9354919Sxy150489 		 * If we are forcing link and we are receiving /C/ ordered
9364919Sxy150489 		 * sets, re-enable auto-negotiation in the TXCW register and
9374919Sxy150489 		 * disable forced link in the Device Control register in an
9384919Sxy150489 		 * attempt to auto-negotiate with our link partner.
9394919Sxy150489 		 */
9404919Sxy150489 		DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
9414919Sxy150489 		E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
9424919Sxy150489 		E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));
9434919Sxy150489 
9447607STed.You@Sun.COM 		mac->serdes_has_link = true;
9454919Sxy150489 	} else if (!(E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW))) {
9464919Sxy150489 		/*
9474919Sxy150489 		 * If we force link for non-auto-negotiation switch, check
9484919Sxy150489 		 * link status based on MAC synchronization for internal
9494919Sxy150489 		 * serdes media type.
9504919Sxy150489 		 */
9514919Sxy150489 		/* SYNCH bit and IV bit are sticky. */
9524919Sxy150489 		usec_delay(10);
9538479SChenlu.Chen@Sun.COM 		rxcw = E1000_READ_REG(hw, E1000_RXCW);
9548479SChenlu.Chen@Sun.COM 		if (rxcw & E1000_RXCW_SYNCH) {
9554919Sxy150489 			if (!(rxcw & E1000_RXCW_IV)) {
9567607STed.You@Sun.COM 				mac->serdes_has_link = true;
9578479SChenlu.Chen@Sun.COM 				DEBUGOUT("SERDES: Link up - forced.\n");
9584919Sxy150489 			}
9594919Sxy150489 		} else {
9607607STed.You@Sun.COM 			mac->serdes_has_link = false;
9618479SChenlu.Chen@Sun.COM 			DEBUGOUT("SERDES: Link down - force failed.\n");
9624919Sxy150489 		}
9634919Sxy150489 	}
9644919Sxy150489 
9654919Sxy150489 	if (E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW)) {
9664919Sxy150489 		status = E1000_READ_REG(hw, E1000_STATUS);
9678479SChenlu.Chen@Sun.COM 		if (status & E1000_STATUS_LU) {
9688479SChenlu.Chen@Sun.COM 			/* SYNCH bit and IV bit are sticky, so reread rxcw. */
9698479SChenlu.Chen@Sun.COM 			usec_delay(10);
9708479SChenlu.Chen@Sun.COM 			rxcw = E1000_READ_REG(hw, E1000_RXCW);
9718479SChenlu.Chen@Sun.COM 			if (rxcw & E1000_RXCW_SYNCH) {
9728479SChenlu.Chen@Sun.COM 				if (!(rxcw & E1000_RXCW_IV)) {
9738479SChenlu.Chen@Sun.COM 					mac->serdes_has_link = true;
9748479SChenlu.Chen@Sun.COM 					DEBUGOUT("SERDES: Link up - autoneg "
9758479SChenlu.Chen@Sun.COM 					    "completed sucessfully.\n");
9768479SChenlu.Chen@Sun.COM 				} else {
9778479SChenlu.Chen@Sun.COM 					mac->serdes_has_link = false;
9788479SChenlu.Chen@Sun.COM 					DEBUGOUT("SERDES: Link down - invalid"
9798479SChenlu.Chen@Sun.COM 					    "codewords detected in autoneg.\n");
9808479SChenlu.Chen@Sun.COM 				}
9818479SChenlu.Chen@Sun.COM 			} else {
9828479SChenlu.Chen@Sun.COM 				mac->serdes_has_link = false;
9838479SChenlu.Chen@Sun.COM 				DEBUGOUT("SERDES: Link down - no sync.\n");
9848479SChenlu.Chen@Sun.COM 			}
9858479SChenlu.Chen@Sun.COM 		} else {
9868479SChenlu.Chen@Sun.COM 			mac->serdes_has_link = false;
9878479SChenlu.Chen@Sun.COM 			DEBUGOUT("SERDES: Link down - autoneg failed\n");
9888479SChenlu.Chen@Sun.COM 		}
9894919Sxy150489 	}
9904919Sxy150489 
9914919Sxy150489 out:
9924919Sxy150489 	return (ret_val);
9934919Sxy150489 }
9944919Sxy150489 
9954919Sxy150489 /*
9964919Sxy150489  * e1000_setup_link_generic - Setup flow control and link settings
9974919Sxy150489  * @hw: pointer to the HW structure
9984919Sxy150489  *
9994919Sxy150489  * Determines which flow control settings to use, then configures flow
10004919Sxy150489  * control.  Calls the appropriate media-specific link configuration
10014919Sxy150489  * function.  Assuming the adapter has a valid link partner, a valid link
10024919Sxy150489  * should be established.  Assumes the hardware has previously been reset
10034919Sxy150489  * and the transmitter and receiver are not enabled.
10044919Sxy150489  */
10054919Sxy150489 s32
e1000_setup_link_generic(struct e1000_hw * hw)10064919Sxy150489 e1000_setup_link_generic(struct e1000_hw *hw)
10074919Sxy150489 {
10084919Sxy150489 	s32 ret_val = E1000_SUCCESS;
10094919Sxy150489 
10104919Sxy150489 	DEBUGFUNC("e1000_setup_link_generic");
10114919Sxy150489 
10124919Sxy150489 	/*
10134919Sxy150489 	 * In the case of the phy reset being blocked, we already have a link.
10144919Sxy150489 	 * We do not need to set it up again.
10154919Sxy150489 	 */
10166735Scc210113 	if (hw->phy.ops.check_reset_block)
10176735Scc210113 		if (hw->phy.ops.check_reset_block(hw))
10186735Scc210113 			goto out;
10194919Sxy150489 
10206735Scc210113 	/*
10218539SChenlu.Chen@Sun.COM 	 * If requested flow control is set to default, set flow control
10228479SChenlu.Chen@Sun.COM 	 * based on the EEPROM flow control settings.
10236735Scc210113 	 */
10248539SChenlu.Chen@Sun.COM 	if (hw->fc.requested_mode == e1000_fc_default) {
10256735Scc210113 		ret_val = e1000_set_default_fc_generic(hw);
10266735Scc210113 		if (ret_val)
10276735Scc210113 			goto out;
10286735Scc210113 	}
10294919Sxy150489 
10304919Sxy150489 	/*
10318479SChenlu.Chen@Sun.COM 	 * Save off the requested flow control mode for use later.  Depending
10328479SChenlu.Chen@Sun.COM 	 * on the link partner's capabilities, we may or may not use this mode.
10334919Sxy150489 	 */
10348539SChenlu.Chen@Sun.COM 	hw->fc.current_mode = hw->fc.requested_mode;
10358479SChenlu.Chen@Sun.COM 	DEBUGOUT1("After fix-ups FlowControl is now = %x\n",
10368479SChenlu.Chen@Sun.COM 	    hw->fc.current_mode);
10374919Sxy150489 
10384919Sxy150489 	/* Call the necessary media_type subroutine to configure the link. */
10396735Scc210113 	ret_val = hw->mac.ops.setup_physical_interface(hw);
10404919Sxy150489 	if (ret_val)
10414919Sxy150489 		goto out;
10424919Sxy150489 
10434919Sxy150489 	/*
10444919Sxy150489 	 * Initialize the flow control address, type, and PAUSE timer
10454919Sxy150489 	 * registers to their default values.  This is done even if flow
10464919Sxy150489 	 * control is disabled, because it does not hurt anything to
10474919Sxy150489 	 * initialize these registers.
10484919Sxy150489 	 */
10494919Sxy150489 	DEBUGOUT("Initializing Flow Control address, type and timer regs\n");
10504919Sxy150489 	E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE);
10514919Sxy150489 	E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH);
10524919Sxy150489 	E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW);
10534919Sxy150489 
10546735Scc210113 	E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time);
10554919Sxy150489 
10564919Sxy150489 	ret_val = e1000_set_fc_watermarks_generic(hw);
10574919Sxy150489 
10584919Sxy150489 out:
10594919Sxy150489 	return (ret_val);
10604919Sxy150489 }
10614919Sxy150489 
10624919Sxy150489 /*
10634919Sxy150489  * e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes
10644919Sxy150489  * @hw: pointer to the HW structure
10654919Sxy150489  *
10664919Sxy150489  * Configures collision distance and flow control for fiber and serdes
10674919Sxy150489  * links.  Upon successful setup, poll for link.
10684919Sxy150489  */
10694919Sxy150489 s32
e1000_setup_fiber_serdes_link_generic(struct e1000_hw * hw)10704919Sxy150489 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw)
10714919Sxy150489 {
10724919Sxy150489 	u32 ctrl;
10734919Sxy150489 	s32 ret_val = E1000_SUCCESS;
10744919Sxy150489 
10754919Sxy150489 	DEBUGFUNC("e1000_setup_fiber_serdes_link_generic");
10764919Sxy150489 
10774919Sxy150489 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
10784919Sxy150489 
10794919Sxy150489 	/* Take the link out of reset */
10804919Sxy150489 	ctrl &= ~E1000_CTRL_LRST;
10814919Sxy150489 
10824919Sxy150489 	e1000_config_collision_dist_generic(hw);
10834919Sxy150489 
10844919Sxy150489 	ret_val = e1000_commit_fc_settings_generic(hw);
10854919Sxy150489 	if (ret_val)
10864919Sxy150489 		goto out;
10874919Sxy150489 
10884919Sxy150489 	/*
10894919Sxy150489 	 * Since auto-negotiation is enabled, take the link out of reset (the
10904919Sxy150489 	 * link will be in reset, because we previously reset the chip). This
10914919Sxy150489 	 * will restart auto-negotiation.  If auto-negotiation is successful
10924919Sxy150489 	 * then the link-up status bit will be set and the flow control enable
10934919Sxy150489 	 * bits (RFCE and TFCE) will be set according to their negotiated value.
10944919Sxy150489 	 */
10954919Sxy150489 	DEBUGOUT("Auto-negotiation enabled\n");
10964919Sxy150489 
10974919Sxy150489 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
10984919Sxy150489 	E1000_WRITE_FLUSH(hw);
10994919Sxy150489 	msec_delay(1);
11004919Sxy150489 
11014919Sxy150489 	/*
11026735Scc210113 	 * For these adapters, the SW definable pin 1 is set when the optics
11034919Sxy150489 	 * detect a signal.  If we have a signal, then poll for a "Link-Up"
11044919Sxy150489 	 * indication.
11054919Sxy150489 	 */
11066735Scc210113 	if (hw->phy.media_type == e1000_media_type_internal_serdes ||
11074919Sxy150489 	    (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) {
11084919Sxy150489 		ret_val = e1000_poll_fiber_serdes_link_generic(hw);
11094919Sxy150489 	} else {
111011143SGuoqing.Zhu@Sun.COM 		/* EMPTY */
11114919Sxy150489 		DEBUGOUT("No signal detected\n");
11124919Sxy150489 	}
11134919Sxy150489 
11144919Sxy150489 out:
11154919Sxy150489 	return (ret_val);
11164919Sxy150489 }
11174919Sxy150489 
11184919Sxy150489 /*
11194919Sxy150489  * e1000_config_collision_dist_generic - Configure collision distance
11204919Sxy150489  * @hw: pointer to the HW structure
11214919Sxy150489  *
11224919Sxy150489  * Configures the collision distance to the default value and is used
11234919Sxy150489  * during link setup. Currently no func pointer exists and all
11244919Sxy150489  * implementations are handled in the generic version of this function.
11254919Sxy150489  */
11264919Sxy150489 void
e1000_config_collision_dist_generic(struct e1000_hw * hw)11274919Sxy150489 e1000_config_collision_dist_generic(struct e1000_hw *hw)
11284919Sxy150489 {
11294919Sxy150489 	u32 tctl;
11304919Sxy150489 
11314919Sxy150489 	DEBUGFUNC("e1000_config_collision_dist_generic");
11324919Sxy150489 
11334919Sxy150489 	tctl = E1000_READ_REG(hw, E1000_TCTL);
11344919Sxy150489 
11354919Sxy150489 	tctl &= ~E1000_TCTL_COLD;
11364919Sxy150489 	tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
11374919Sxy150489 
11384919Sxy150489 	E1000_WRITE_REG(hw, E1000_TCTL, tctl);
11394919Sxy150489 	E1000_WRITE_FLUSH(hw);
11404919Sxy150489 }
11414919Sxy150489 
11424919Sxy150489 /*
11434919Sxy150489  * e1000_poll_fiber_serdes_link_generic - Poll for link up
11444919Sxy150489  * @hw: pointer to the HW structure
11454919Sxy150489  *
11464919Sxy150489  * Polls for link up by reading the status register, if link fails to come
11474919Sxy150489  * up with auto-negotiation, then the link is forced if a signal is detected.
11484919Sxy150489  */
11494919Sxy150489 s32
e1000_poll_fiber_serdes_link_generic(struct e1000_hw * hw)11504919Sxy150489 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
11514919Sxy150489 {
11524919Sxy150489 	struct e1000_mac_info *mac = &hw->mac;
11534919Sxy150489 	u32 i, status;
11544919Sxy150489 	s32 ret_val = E1000_SUCCESS;
11554919Sxy150489 
11564919Sxy150489 	DEBUGFUNC("e1000_poll_fiber_serdes_link_generic");
11574919Sxy150489 
11584919Sxy150489 	/*
11594919Sxy150489 	 * If we have a signal (the cable is plugged in, or assumed true for
11604919Sxy150489 	 * serdes media) then poll for a "Link-Up" indication in the Device
11614919Sxy150489 	 * Status Register.  Time-out if a link isn't seen in 500 milliseconds
11624919Sxy150489 	 * seconds (Auto-negotiation should complete in less than 500
11634919Sxy150489 	 * milliseconds even if the other end is doing it in SW).
11644919Sxy150489 	 */
11654919Sxy150489 	for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) {
11664919Sxy150489 		msec_delay(10);
11674919Sxy150489 		status = E1000_READ_REG(hw, E1000_STATUS);
11684919Sxy150489 		if (status & E1000_STATUS_LU)
11694919Sxy150489 			break;
11704919Sxy150489 	}
11714919Sxy150489 	if (i == FIBER_LINK_UP_LIMIT) {
11724919Sxy150489 		DEBUGOUT("Never got a valid link from auto-neg!!!\n");
11734919Sxy150489 		mac->autoneg_failed = 1;
11744919Sxy150489 		/*
11754919Sxy150489 		 * AutoNeg failed to achieve a link, so we'll call
11764919Sxy150489 		 * mac->check_for_link. This routine will force the link up if
11774919Sxy150489 		 * we detect a signal. This will allow us to communicate with
11784919Sxy150489 		 * non-autonegotiating link partners.
11794919Sxy150489 		 */
11806735Scc210113 		ret_val = hw->mac.ops.check_for_link(hw);
11814919Sxy150489 		if (ret_val) {
11824919Sxy150489 			DEBUGOUT("Error while checking for link\n");
11834919Sxy150489 			goto out;
11844919Sxy150489 		}
11854919Sxy150489 		mac->autoneg_failed = 0;
11864919Sxy150489 	} else {
11874919Sxy150489 		mac->autoneg_failed = 0;
11884919Sxy150489 		DEBUGOUT("Valid Link Found\n");
11894919Sxy150489 	}
11904919Sxy150489 
11914919Sxy150489 out:
11924919Sxy150489 	return (ret_val);
11934919Sxy150489 }
11944919Sxy150489 
11954919Sxy150489 /*
11964919Sxy150489  * e1000_commit_fc_settings_generic - Configure flow control
11974919Sxy150489  * @hw: pointer to the HW structure
11984919Sxy150489  *
11994919Sxy150489  * Write the flow control settings to the Transmit Config Word Register (TXCW)
12004919Sxy150489  * base on the flow control settings in e1000_mac_info.
12014919Sxy150489  */
12024919Sxy150489 s32
e1000_commit_fc_settings_generic(struct e1000_hw * hw)12034919Sxy150489 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
12044919Sxy150489 {
12054919Sxy150489 	struct e1000_mac_info *mac = &hw->mac;
12064919Sxy150489 	u32 txcw;
12074919Sxy150489 	s32 ret_val = E1000_SUCCESS;
12084919Sxy150489 
12094919Sxy150489 	DEBUGFUNC("e1000_commit_fc_settings_generic");
12104919Sxy150489 
12114919Sxy150489 	/*
12124919Sxy150489 	 * Check for a software override of the flow control settings, and
12134919Sxy150489 	 * setup the device accordingly.  If auto-negotiation is enabled, then
12144919Sxy150489 	 * software will have to set the "PAUSE" bits to the correct value in
12154919Sxy150489 	 * the Transmit Config Word Register (TXCW) and re-start auto-
12164919Sxy150489 	 * negotiation.  However, if auto-negotiation is disabled, then
12174919Sxy150489 	 * software will have to manually configure the two flow control enable
12184919Sxy150489 	 * bits in the CTRL register.
12194919Sxy150489 	 *
12204919Sxy150489 	 * The possible values of the "fc" parameter are:
12214919Sxy150489 	 * 0:	Flow control is completely disabled
12224919Sxy150489 	 * 1:	Rx flow control is enabled (we can receive pause frames,
12234919Sxy150489 	 *	but not send pause frames).
12244919Sxy150489 	 * 2:	Tx flow control is enabled (we can send pause frames but we
12254919Sxy150489 	 *	do not support receiving pause frames).
12266735Scc210113 	 * 3:	Both Rx and Tx flow control (symmetric) are enabled.
12274919Sxy150489 	 */
12288479SChenlu.Chen@Sun.COM 	switch (hw->fc.current_mode) {
12294919Sxy150489 	case e1000_fc_none:
12304919Sxy150489 		/* Flow control completely disabled by a software over-ride. */
12314919Sxy150489 		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
12324919Sxy150489 		break;
12334919Sxy150489 	case e1000_fc_rx_pause:
12344919Sxy150489 		/*
12356735Scc210113 		 * Rx Flow control is enabled and Tx Flow control is disabled
12364919Sxy150489 		 * by a software over-ride. Since there really isn't a way to
12376735Scc210113 		 * advertise that we are capable of Rx Pause ONLY, we will
12384919Sxy150489 		 * advertise that we support both symmetric and asymmetric RX
12394919Sxy150489 		 * PAUSE.  Later, we will disable the adapter's ability to send
12404919Sxy150489 		 * PAUSE frames.
12414919Sxy150489 		 */
12424919Sxy150489 		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
12434919Sxy150489 		break;
12444919Sxy150489 	case e1000_fc_tx_pause:
12454919Sxy150489 		/*
12466735Scc210113 		 * Tx Flow control is enabled, and Rx Flow control is disabled,
12474919Sxy150489 		 * by a software over-ride.
12484919Sxy150489 		 */
12494919Sxy150489 		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
12504919Sxy150489 		break;
12514919Sxy150489 	case e1000_fc_full:
12524919Sxy150489 		/*
12536735Scc210113 		 * Flow control (both Rx and Tx) is enabled by a software
12544919Sxy150489 		 * over-ride.
12554919Sxy150489 		 */
12564919Sxy150489 		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
12574919Sxy150489 		break;
12584919Sxy150489 	default:
12594919Sxy150489 		DEBUGOUT("Flow control param set incorrectly\n");
12604919Sxy150489 		ret_val = -E1000_ERR_CONFIG;
12614919Sxy150489 		goto out;
12624919Sxy150489 	}
12634919Sxy150489 
12644919Sxy150489 	E1000_WRITE_REG(hw, E1000_TXCW, txcw);
12654919Sxy150489 	mac->txcw = txcw;
12664919Sxy150489 
12674919Sxy150489 out:
12684919Sxy150489 	return (ret_val);
12694919Sxy150489 }
12704919Sxy150489 
12714919Sxy150489 /*
12724919Sxy150489  * e1000_set_fc_watermarks_generic - Set flow control high/low watermarks
12734919Sxy150489  * @hw: pointer to the HW structure
12744919Sxy150489  *
12754919Sxy150489  * Sets the flow control high/low threshold (watermark) registers.  If
12764919Sxy150489  * flow control XON frame transmission is enabled, then set XON frame
12776735Scc210113  * transmission as well.
12784919Sxy150489  */
12794919Sxy150489 s32
e1000_set_fc_watermarks_generic(struct e1000_hw * hw)12804919Sxy150489 e1000_set_fc_watermarks_generic(struct e1000_hw *hw)
12814919Sxy150489 {
12824919Sxy150489 	s32 ret_val = E1000_SUCCESS;
12834919Sxy150489 	u32 fcrtl = 0, fcrth = 0;
12844919Sxy150489 
12854919Sxy150489 	DEBUGFUNC("e1000_set_fc_watermarks_generic");
12864919Sxy150489 
12874919Sxy150489 	/*
12884919Sxy150489 	 * Set the flow control receive threshold registers.  Normally, these
12894919Sxy150489 	 * registers will be set to a default threshold that may be adjusted
12904919Sxy150489 	 * later by the driver's runtime code.  However, if the ability to
12914919Sxy150489 	 * transmit pause frames is not enabled, then these registers will be
12924919Sxy150489 	 * set to 0.
12934919Sxy150489 	 */
12948479SChenlu.Chen@Sun.COM 	if (hw->fc.current_mode & e1000_fc_tx_pause) {
12954919Sxy150489 		/*
12964919Sxy150489 		 * We need to set up the Receive Threshold high and low water
12974919Sxy150489 		 * marks as well as (optionally) enabling the transmission of
12984919Sxy150489 		 * XON frames.
12994919Sxy150489 		 */
13006735Scc210113 		fcrtl = hw->fc.low_water;
13016735Scc210113 		if (hw->fc.send_xon)
13024919Sxy150489 			fcrtl |= E1000_FCRTL_XONE;
13034919Sxy150489 
13046735Scc210113 		fcrth = hw->fc.high_water;
13054919Sxy150489 	}
13064919Sxy150489 	E1000_WRITE_REG(hw, E1000_FCRTL, fcrtl);
13074919Sxy150489 	E1000_WRITE_REG(hw, E1000_FCRTH, fcrth);
13084919Sxy150489 
13094919Sxy150489 	return (ret_val);
13104919Sxy150489 }
13114919Sxy150489 
13124919Sxy150489 /*
13134919Sxy150489  * e1000_set_default_fc_generic - Set flow control default values
13144919Sxy150489  * @hw: pointer to the HW structure
13154919Sxy150489  *
13164919Sxy150489  * Read the EEPROM for the default values for flow control and store the
13174919Sxy150489  * values.
13184919Sxy150489  */
13194919Sxy150489 s32
e1000_set_default_fc_generic(struct e1000_hw * hw)13204919Sxy150489 e1000_set_default_fc_generic(struct e1000_hw *hw)
13214919Sxy150489 {
13224919Sxy150489 	s32 ret_val = E1000_SUCCESS;
13234919Sxy150489 	u16 nvm_data;
13244919Sxy150489 
13254919Sxy150489 	DEBUGFUNC("e1000_set_default_fc_generic");
13264919Sxy150489 
13274919Sxy150489 	/*
13284919Sxy150489 	 * Read and store word 0x0F of the EEPROM. This word contains bits
13294919Sxy150489 	 * that determine the hardware's default PAUSE (flow control) mode, a
13304919Sxy150489 	 * bit that determines whether the HW defaults to enabling or
13314919Sxy150489 	 * disabling auto-negotiation, and the direction of the SW defined
13324919Sxy150489 	 * pins. If there is no SW over-ride of the flow control setting, then
13334919Sxy150489 	 * the variable hw->fc will be initialized based on a value in the
13344919Sxy150489 	 * EEPROM.
13354919Sxy150489 	 */
13366735Scc210113 	ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
13374919Sxy150489 
13384919Sxy150489 	if (ret_val) {
13394919Sxy150489 		DEBUGOUT("NVM Read Error\n");
13404919Sxy150489 		goto out;
13414919Sxy150489 	}
13424919Sxy150489 
13434919Sxy150489 	if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
13448539SChenlu.Chen@Sun.COM 		hw->fc.requested_mode = e1000_fc_none;
13454919Sxy150489 	else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
13464919Sxy150489 	    NVM_WORD0F_ASM_DIR)
13478539SChenlu.Chen@Sun.COM 		hw->fc.requested_mode = e1000_fc_tx_pause;
13484919Sxy150489 	else
13498539SChenlu.Chen@Sun.COM 		hw->fc.requested_mode = e1000_fc_full;
13504919Sxy150489 
13514919Sxy150489 out:
13524919Sxy150489 	return (ret_val);
13534919Sxy150489 }
13544919Sxy150489 
13554919Sxy150489 /*
13564919Sxy150489  * e1000_force_mac_fc_generic - Force the MAC's flow control settings
13574919Sxy150489  * @hw: pointer to the HW structure
13584919Sxy150489  *
13594919Sxy150489  * Force the MAC's flow control settings.  Sets the TFCE and RFCE bits in the
13604919Sxy150489  * device control register to reflect the adapter settings.  TFCE and RFCE
13614919Sxy150489  * need to be explicitly set by software when a copper PHY is used because
13624919Sxy150489  * autonegotiation is managed by the PHY rather than the MAC.  Software must
13634919Sxy150489  * also configure these bits when link is forced on a fiber connection.
13644919Sxy150489  */
13654919Sxy150489 s32
e1000_force_mac_fc_generic(struct e1000_hw * hw)13664919Sxy150489 e1000_force_mac_fc_generic(struct e1000_hw *hw)
13674919Sxy150489 {
13684919Sxy150489 	u32 ctrl;
13694919Sxy150489 	s32 ret_val = E1000_SUCCESS;
13704919Sxy150489 
13714919Sxy150489 	DEBUGFUNC("e1000_force_mac_fc_generic");
13724919Sxy150489 
13734919Sxy150489 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
13744919Sxy150489 
13754919Sxy150489 	/*
13764919Sxy150489 	 * Because we didn't get link via the internal auto-negotiation
13774919Sxy150489 	 * mechanism (we either forced link or we got link via PHY auto-neg),
13784919Sxy150489 	 * we have to manually enable/disable transmit an receive flow
13794919Sxy150489 	 * control.
13804919Sxy150489 	 *
13814919Sxy150489 	 * The "Case" statement below enables/disable flow control according to
13828479SChenlu.Chen@Sun.COM 	 * the "hw->fc.current_mode" parameter.
13834919Sxy150489 	 *
13844919Sxy150489 	 * The possible values of the "fc" parameter are:
13854919Sxy150489 	 * 0:	Flow control is completely disabled
13864919Sxy150489 	 * 1:	Rx flow control is enabled (we can receive pause
13874919Sxy150489 	 *	frames but not send pause frames).
13884919Sxy150489 	 * 2:	Tx flow control is enabled (we can send pause frames
13894919Sxy150489 	 *	frames but we do not receive pause frames).
13906735Scc210113 	 * 3:	Both Rx and Tx flow control (symmetric) is enabled.
13914919Sxy150489 	 * other:  No other values should be possible at this point.
13924919Sxy150489 	 */
13938479SChenlu.Chen@Sun.COM 	DEBUGOUT1("hw->fc.current_mode = %u\n", hw->fc.current_mode);
13944919Sxy150489 
13958479SChenlu.Chen@Sun.COM 	switch (hw->fc.current_mode) {
13964919Sxy150489 	case e1000_fc_none:
13974919Sxy150489 		ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
13984919Sxy150489 		break;
13994919Sxy150489 	case e1000_fc_rx_pause:
14004919Sxy150489 		ctrl &= (~E1000_CTRL_TFCE);
14014919Sxy150489 		ctrl |= E1000_CTRL_RFCE;
14024919Sxy150489 		break;
14034919Sxy150489 	case e1000_fc_tx_pause:
14044919Sxy150489 		ctrl &= (~E1000_CTRL_RFCE);
14054919Sxy150489 		ctrl |= E1000_CTRL_TFCE;
14064919Sxy150489 		break;
14074919Sxy150489 	case e1000_fc_full:
14084919Sxy150489 		ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
14094919Sxy150489 		break;
14104919Sxy150489 	default:
14114919Sxy150489 		DEBUGOUT("Flow control param set incorrectly\n");
14124919Sxy150489 		ret_val = -E1000_ERR_CONFIG;
14134919Sxy150489 		goto out;
14144919Sxy150489 	}
14154919Sxy150489 
14164919Sxy150489 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
14174919Sxy150489 
14184919Sxy150489 out:
14194919Sxy150489 	return (ret_val);
14204919Sxy150489 }
14214919Sxy150489 
14224919Sxy150489 /*
14234919Sxy150489  * e1000_config_fc_after_link_up_generic - Configures flow control after link
14244919Sxy150489  * @hw: pointer to the HW structure
14254919Sxy150489  *
14264919Sxy150489  * Checks the status of auto-negotiation after link up to ensure that the
14274919Sxy150489  * speed and duplex were not forced.  If the link needed to be forced, then
14284919Sxy150489  * flow control needs to be forced also.  If auto-negotiation is enabled
14294919Sxy150489  * and did not fail, then we configure flow control based on our link
14304919Sxy150489  * partner.
14314919Sxy150489  */
14324919Sxy150489 s32
e1000_config_fc_after_link_up_generic(struct e1000_hw * hw)14334919Sxy150489 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
14344919Sxy150489 {
14354919Sxy150489 	struct e1000_mac_info *mac = &hw->mac;
14364919Sxy150489 	s32 ret_val = E1000_SUCCESS;
14374919Sxy150489 	u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
14384919Sxy150489 	u16 speed, duplex;
14394919Sxy150489 
14404919Sxy150489 	DEBUGFUNC("e1000_config_fc_after_link_up_generic");
14414919Sxy150489 
14424919Sxy150489 	/*
14434919Sxy150489 	 * Check for the case where we have fiber media and auto-neg failed so
14444919Sxy150489 	 * we had to force link.  In this case, we need to force the
14454919Sxy150489 	 * configuration of the MAC to match the "fc" parameter.
14464919Sxy150489 	 */
14474919Sxy150489 	if (mac->autoneg_failed) {
14486735Scc210113 		if (hw->phy.media_type == e1000_media_type_fiber ||
14496735Scc210113 		    hw->phy.media_type == e1000_media_type_internal_serdes)
14504919Sxy150489 			ret_val = e1000_force_mac_fc_generic(hw);
14514919Sxy150489 	} else {
14526735Scc210113 		if (hw->phy.media_type == e1000_media_type_copper)
14534919Sxy150489 			ret_val = e1000_force_mac_fc_generic(hw);
14544919Sxy150489 	}
14554919Sxy150489 
14564919Sxy150489 	if (ret_val) {
14574919Sxy150489 		DEBUGOUT("Error forcing flow control settings\n");
14584919Sxy150489 		goto out;
14594919Sxy150489 	}
14604919Sxy150489 
14614919Sxy150489 	/*
14624919Sxy150489 	 * Check for the case where we have copper media and auto-neg is
14634919Sxy150489 	 * enabled.  In this case, we need to check and see if Auto-Neg has
14644919Sxy150489 	 * completed, and if so, how the PHY and link partner has flow control
14654919Sxy150489 	 * configured.
14664919Sxy150489 	 */
14676735Scc210113 	if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) {
14684919Sxy150489 		/*
14694919Sxy150489 		 * Read the MII Status Register and check to see if AutoNeg
14704919Sxy150489 		 * has completed.  We read this twice because this reg has
14714919Sxy150489 		 * some "sticky" (latched) bits.
14724919Sxy150489 		 */
14738479SChenlu.Chen@Sun.COM 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
14744919Sxy150489 		if (ret_val)
14754919Sxy150489 			goto out;
14768479SChenlu.Chen@Sun.COM 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
14774919Sxy150489 		if (ret_val)
14784919Sxy150489 			goto out;
14794919Sxy150489 
14804919Sxy150489 		if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
14814919Sxy150489 			DEBUGOUT("Copper PHY and Auto Neg "
14824919Sxy150489 			    "has not completed.\n");
14834919Sxy150489 			goto out;
14844919Sxy150489 		}
14854919Sxy150489 		/*
14864919Sxy150489 		 * The AutoNeg process has completed, so we now need to read
14874919Sxy150489 		 * both the Auto Negotiation Advertisement Register (Address
14884919Sxy150489 		 * 4) and the Auto_Negotiation Base Page Ability Register
14894919Sxy150489 		 * (Address 5) to determine how flow control was negotiated.
14904919Sxy150489 		 */
14918479SChenlu.Chen@Sun.COM 		ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,
14924919Sxy150489 		    &mii_nway_adv_reg);
14934919Sxy150489 		if (ret_val)
14944919Sxy150489 			goto out;
14958479SChenlu.Chen@Sun.COM 		ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,
14964919Sxy150489 		    &mii_nway_lp_ability_reg);
14974919Sxy150489 		if (ret_val)
14984919Sxy150489 			goto out;
14994919Sxy150489 
15004919Sxy150489 		/*
15014919Sxy150489 		 * Two bits in the Auto Negotiation Advertisement Register
15024919Sxy150489 		 * (Address 4) and two bits in the Auto Negotiation Base
15034919Sxy150489 		 * Page Ability Register (Address 5) determine flow control
15044919Sxy150489 		 * for both the PHY and the link partner.  The following
15054919Sxy150489 		 * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
15064919Sxy150489 		 * 1999, describes these PAUSE resolution bits and how flow
15074919Sxy150489 		 * control is determined based upon these settings.
15084919Sxy150489 		 * NOTE:  DC = Don't Care
15094919Sxy150489 		 *
15104919Sxy150489 		 *   LOCAL DEVICE  |   LINK PARTNER
15114919Sxy150489 		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
15124919Sxy150489 		 * ------|---------|-------|---------|--------------------
15134919Sxy150489 		 *   0   |    0    |  DC   |   DC    | e1000_fc_none
15144919Sxy150489 		 *   0   |    1    |   0   |   DC    | e1000_fc_none
15154919Sxy150489 		 *   0   |    1    |   1   |    0    | e1000_fc_none
15164919Sxy150489 		 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
15174919Sxy150489 		 *   1   |    0    |   0   |   DC    | e1000_fc_none
15184919Sxy150489 		 *   1   |   DC    |   1   |   DC    | e1000_fc_full
15194919Sxy150489 		 *   1   |    1    |   0   |    0    | e1000_fc_none
15204919Sxy150489 		 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
15214919Sxy150489 		 *
15224919Sxy150489 		 * Are both PAUSE bits set to 1?  If so, this implies
15234919Sxy150489 		 * Symmetric Flow Control is enabled at both ends.  The
15244919Sxy150489 		 * ASM_DIR bits are irrelevant per the spec.
15254919Sxy150489 		 *
15264919Sxy150489 		 * For Symmetric Flow Control:
15274919Sxy150489 		 *
15284919Sxy150489 		 *   LOCAL DEVICE  |   LINK PARTNER
15294919Sxy150489 		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
15304919Sxy150489 		 * ------|---------|-------|---------|--------------------
15314919Sxy150489 		 *   1   |   DC    |   1   |   DC    | E1000_fc_full
15324919Sxy150489 		 *
15334919Sxy150489 		 */
15344919Sxy150489 		if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
15354919Sxy150489 		    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
15364919Sxy150489 			/*
15376735Scc210113 			 * Now we need to check if the user selected Rx ONLY
15384919Sxy150489 			 * of pause frames.  In this case, we had to advertise
15394919Sxy150489 			 * FULL flow control because we could not advertise RX
15404919Sxy150489 			 * ONLY. Hence, we must now check to see if we need to
15414919Sxy150489 			 * turn OFF  the TRANSMISSION of PAUSE frames.
15424919Sxy150489 			 */
15438479SChenlu.Chen@Sun.COM 			if (hw->fc.requested_mode == e1000_fc_full) {
15448479SChenlu.Chen@Sun.COM 				hw->fc.current_mode = e1000_fc_full;
15454919Sxy150489 				DEBUGOUT("Flow Control = FULL.\r\n");
15464919Sxy150489 			} else {
15478479SChenlu.Chen@Sun.COM 				hw->fc.current_mode = e1000_fc_rx_pause;
15484919Sxy150489 				DEBUGOUT("Flow Control = "
15494919Sxy150489 				    "RX PAUSE frames only.\r\n");
15504919Sxy150489 			}
15514919Sxy150489 		}
15524919Sxy150489 		/*
15534919Sxy150489 		 * For receiving PAUSE frames ONLY.
15544919Sxy150489 		 *
15554919Sxy150489 		 *   LOCAL DEVICE  |   LINK PARTNER
15564919Sxy150489 		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
15574919Sxy150489 		 * ------|---------|-------|---------|--------------------
15584919Sxy150489 		 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
15594919Sxy150489 		 */
15604919Sxy150489 		else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
15614919Sxy150489 		    (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
15624919Sxy150489 		    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
15634919Sxy150489 		    (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
15648479SChenlu.Chen@Sun.COM 			hw->fc.current_mode = e1000_fc_tx_pause;
15654919Sxy150489 			DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n");
15664919Sxy150489 		}
15674919Sxy150489 		/*
15684919Sxy150489 		 * For transmitting PAUSE frames ONLY.
15694919Sxy150489 		 *
15704919Sxy150489 		 *   LOCAL DEVICE  |   LINK PARTNER
15714919Sxy150489 		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
15724919Sxy150489 		 * ------|---------|-------|---------|--------------------
15734919Sxy150489 		 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
15744919Sxy150489 		 */
15754919Sxy150489 		else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
15764919Sxy150489 		    (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
15774919Sxy150489 		    !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
15784919Sxy150489 		    (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
15798479SChenlu.Chen@Sun.COM 			hw->fc.current_mode = e1000_fc_rx_pause;
15804919Sxy150489 			DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
15816735Scc210113 		} else {
15826735Scc210113 			/*
15836735Scc210113 			 * Per the IEEE spec, at this point flow control
15846735Scc210113 			 * should be disabled.
15856735Scc210113 			 */
15868479SChenlu.Chen@Sun.COM 			hw->fc.current_mode = e1000_fc_none;
15874919Sxy150489 			DEBUGOUT("Flow Control = NONE.\r\n");
15884919Sxy150489 		}
15894919Sxy150489 
15904919Sxy150489 		/*
15914919Sxy150489 		 * Now we need to do one last check...  If we auto- negotiated
15924919Sxy150489 		 * to HALF DUPLEX, flow control should not be enabled per IEEE
15934919Sxy150489 		 * 802.3 spec.
15944919Sxy150489 		 */
15956735Scc210113 		ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
15964919Sxy150489 		if (ret_val) {
15974919Sxy150489 			DEBUGOUT("Error getting link speed and duplex\n");
15984919Sxy150489 			goto out;
15994919Sxy150489 		}
16004919Sxy150489 
16014919Sxy150489 		if (duplex == HALF_DUPLEX)
16028479SChenlu.Chen@Sun.COM 			hw->fc.current_mode = e1000_fc_none;
16034919Sxy150489 
16044919Sxy150489 		/*
16054919Sxy150489 		 * Now we call a subroutine to actually force the MAC
16064919Sxy150489 		 * controller to use the correct flow control settings.
16074919Sxy150489 		 */
16084919Sxy150489 		ret_val = e1000_force_mac_fc_generic(hw);
16094919Sxy150489 		if (ret_val) {
16104919Sxy150489 			DEBUGOUT("Error forcing flow control settings\n");
16114919Sxy150489 			goto out;
16124919Sxy150489 		}
16134919Sxy150489 	}
16144919Sxy150489 
16154919Sxy150489 out:
16164919Sxy150489 	return (ret_val);
16174919Sxy150489 }
16184919Sxy150489 
16194919Sxy150489 /*
16206735Scc210113  * e1000_get_speed_and_duplex_copper_generic - Retrieve current speed/duplex
16214919Sxy150489  * @hw: pointer to the HW structure
16224919Sxy150489  * @speed: stores the current speed
16234919Sxy150489  * @duplex: stores the current duplex
16244919Sxy150489  *
16254919Sxy150489  * Read the status register for the current speed/duplex and store the current
16264919Sxy150489  * speed and duplex for copper connections.
16274919Sxy150489  */
16284919Sxy150489 s32
e1000_get_speed_and_duplex_copper_generic(struct e1000_hw * hw,u16 * speed,u16 * duplex)16294919Sxy150489 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
16304919Sxy150489     u16 *duplex)
16314919Sxy150489 {
16324919Sxy150489 	u32 status;
16334919Sxy150489 
16344919Sxy150489 	DEBUGFUNC("e1000_get_speed_and_duplex_copper_generic");
16354919Sxy150489 
16364919Sxy150489 	status = E1000_READ_REG(hw, E1000_STATUS);
16374919Sxy150489 	if (status & E1000_STATUS_SPEED_1000) {
16384919Sxy150489 		*speed = SPEED_1000;
16394919Sxy150489 		DEBUGOUT("1000 Mbs, ");
16404919Sxy150489 	} else if (status & E1000_STATUS_SPEED_100) {
16414919Sxy150489 		*speed = SPEED_100;
16424919Sxy150489 		DEBUGOUT("100 Mbs, ");
16434919Sxy150489 	} else {
16444919Sxy150489 		*speed = SPEED_10;
16454919Sxy150489 		DEBUGOUT("10 Mbs, ");
16464919Sxy150489 	}
16474919Sxy150489 
16484919Sxy150489 	if (status & E1000_STATUS_FD) {
16494919Sxy150489 		*duplex = FULL_DUPLEX;
16504919Sxy150489 		DEBUGOUT("Full Duplex\n");
16514919Sxy150489 	} else {
16524919Sxy150489 		*duplex = HALF_DUPLEX;
16534919Sxy150489 		DEBUGOUT("Half Duplex\n");
16544919Sxy150489 	}
16554919Sxy150489 
16564919Sxy150489 	return (E1000_SUCCESS);
16574919Sxy150489 }
16584919Sxy150489 
16594919Sxy150489 /*
16606735Scc210113  * e1000_get_speed_and_duplex_fiber_generic - Retrieve current speed/duplex
16614919Sxy150489  * @hw: pointer to the HW structure
16624919Sxy150489  * @speed: stores the current speed
16634919Sxy150489  * @duplex: stores the current duplex
16644919Sxy150489  *
16654919Sxy150489  * Sets the speed and duplex to gigabit full duplex (the only possible option)
16664919Sxy150489  * for fiber/serdes links.
16674919Sxy150489  */
16684919Sxy150489 s32
e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw * hw,u16 * speed,u16 * duplex)16694919Sxy150489 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
16704919Sxy150489     u16 *speed, u16 *duplex)
16714919Sxy150489 {
16724919Sxy150489 	DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic");
16736735Scc210113 	UNREFERENCED_1PARAMETER(hw);
16744919Sxy150489 
16754919Sxy150489 	*speed = SPEED_1000;
16764919Sxy150489 	*duplex = FULL_DUPLEX;
16774919Sxy150489 
16784919Sxy150489 	return (E1000_SUCCESS);
16794919Sxy150489 }
16804919Sxy150489 
16814919Sxy150489 /*
16824919Sxy150489  * e1000_get_hw_semaphore_generic - Acquire hardware semaphore
16834919Sxy150489  * @hw: pointer to the HW structure
16844919Sxy150489  *
16854919Sxy150489  * Acquire the HW semaphore to access the PHY or NVM
16864919Sxy150489  */
16874919Sxy150489 s32
e1000_get_hw_semaphore_generic(struct e1000_hw * hw)16884919Sxy150489 e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
16894919Sxy150489 {
16904919Sxy150489 	u32 swsm;
16914919Sxy150489 	s32 ret_val = E1000_SUCCESS;
16924919Sxy150489 	s32 timeout = hw->nvm.word_size + 1;
16934919Sxy150489 	s32 i = 0;
16944919Sxy150489 
16954919Sxy150489 	DEBUGFUNC("e1000_get_hw_semaphore_generic");
16964919Sxy150489 
16974919Sxy150489 	/* Get the SW semaphore */
16984919Sxy150489 	while (i < timeout) {
16994919Sxy150489 		swsm = E1000_READ_REG(hw, E1000_SWSM);
17004919Sxy150489 		if (!(swsm & E1000_SWSM_SMBI))
17014919Sxy150489 			break;
17024919Sxy150489 
17034919Sxy150489 		usec_delay(50);
17044919Sxy150489 		i++;
17054919Sxy150489 	}
17064919Sxy150489 
17074919Sxy150489 	if (i == timeout) {
17084919Sxy150489 		DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
17094919Sxy150489 		ret_val = -E1000_ERR_NVM;
17104919Sxy150489 		goto out;
17114919Sxy150489 	}
17124919Sxy150489 
17134919Sxy150489 	/* Get the FW semaphore. */
17144919Sxy150489 	for (i = 0; i < timeout; i++) {
17154919Sxy150489 		swsm = E1000_READ_REG(hw, E1000_SWSM);
17164919Sxy150489 		E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
17174919Sxy150489 
17184919Sxy150489 		/* Semaphore acquired if bit latched */
17194919Sxy150489 		if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)
17204919Sxy150489 			break;
17214919Sxy150489 
17224919Sxy150489 		usec_delay(50);
17234919Sxy150489 	}
17244919Sxy150489 
17254919Sxy150489 	if (i == timeout) {
17264919Sxy150489 		/* Release semaphores */
17274919Sxy150489 		e1000_put_hw_semaphore_generic(hw);
17284919Sxy150489 		DEBUGOUT("Driver can't access the NVM\n");
17294919Sxy150489 		ret_val = -E1000_ERR_NVM;
17304919Sxy150489 		goto out;
17314919Sxy150489 	}
17324919Sxy150489 
17334919Sxy150489 out:
17344919Sxy150489 	return (ret_val);
17354919Sxy150489 }
17364919Sxy150489 
17374919Sxy150489 /*
17384919Sxy150489  * e1000_put_hw_semaphore_generic - Release hardware semaphore
17394919Sxy150489  * @hw: pointer to the HW structure
17404919Sxy150489  *
17414919Sxy150489  * Release hardware semaphore used to access the PHY or NVM
17424919Sxy150489  */
17434919Sxy150489 void
e1000_put_hw_semaphore_generic(struct e1000_hw * hw)17444919Sxy150489 e1000_put_hw_semaphore_generic(struct e1000_hw *hw)
17454919Sxy150489 {
17464919Sxy150489 	u32 swsm;
17474919Sxy150489 
17484919Sxy150489 	DEBUGFUNC("e1000_put_hw_semaphore_generic");
17494919Sxy150489 
17504919Sxy150489 	swsm = E1000_READ_REG(hw, E1000_SWSM);
17514919Sxy150489 
17524919Sxy150489 	swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
17534919Sxy150489 
17544919Sxy150489 	E1000_WRITE_REG(hw, E1000_SWSM, swsm);
17554919Sxy150489 }
17564919Sxy150489 
17574919Sxy150489 /*
17584919Sxy150489  * e1000_get_auto_rd_done_generic - Check for auto read completion
17594919Sxy150489  * @hw: pointer to the HW structure
17604919Sxy150489  *
17614919Sxy150489  * Check EEPROM for Auto Read done bit.
17624919Sxy150489  */
17634919Sxy150489 s32
e1000_get_auto_rd_done_generic(struct e1000_hw * hw)17644919Sxy150489 e1000_get_auto_rd_done_generic(struct e1000_hw *hw)
17654919Sxy150489 {
17664919Sxy150489 	s32 i = 0;
17674919Sxy150489 	s32 ret_val = E1000_SUCCESS;
17684919Sxy150489 
17694919Sxy150489 	DEBUGFUNC("e1000_get_auto_rd_done_generic");
17704919Sxy150489 
17714919Sxy150489 	while (i < AUTO_READ_DONE_TIMEOUT) {
17724919Sxy150489 		if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_AUTO_RD)
17734919Sxy150489 			break;
17744919Sxy150489 		msec_delay(1);
17754919Sxy150489 		i++;
17764919Sxy150489 	}
17774919Sxy150489 
17784919Sxy150489 	if (i == AUTO_READ_DONE_TIMEOUT) {
17794919Sxy150489 		DEBUGOUT("Auto read by HW from NVM has not completed.\n");
17804919Sxy150489 		ret_val = -E1000_ERR_RESET;
17814919Sxy150489 		goto out;
17824919Sxy150489 	}
17834919Sxy150489 
17844919Sxy150489 out:
17854919Sxy150489 	return (ret_val);
17864919Sxy150489 }
17874919Sxy150489 
17884919Sxy150489 /*
17894919Sxy150489  * e1000_valid_led_default_generic - Verify a valid default LED config
17904919Sxy150489  * @hw: pointer to the HW structure
17914919Sxy150489  * @data: pointer to the NVM (EEPROM)
17924919Sxy150489  *
17934919Sxy150489  * Read the EEPROM for the current default LED configuration.  If the
17944919Sxy150489  * LED configuration is not valid, set to a valid LED configuration.
17954919Sxy150489  */
17964919Sxy150489 s32
e1000_valid_led_default_generic(struct e1000_hw * hw,u16 * data)17974919Sxy150489 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data)
17984919Sxy150489 {
17994919Sxy150489 	s32 ret_val;
18004919Sxy150489 
18014919Sxy150489 	DEBUGFUNC("e1000_valid_led_default_generic");
18024919Sxy150489 
18036735Scc210113 	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
18044919Sxy150489 	if (ret_val) {
18054919Sxy150489 		DEBUGOUT("NVM Read Error\n");
18064919Sxy150489 		goto out;
18074919Sxy150489 	}
18084919Sxy150489 
18094919Sxy150489 	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
18104919Sxy150489 		*data = ID_LED_DEFAULT;
18114919Sxy150489 
18124919Sxy150489 out:
18134919Sxy150489 	return (ret_val);
18144919Sxy150489 }
18154919Sxy150489 
18164919Sxy150489 /*
18174919Sxy150489  * e1000_id_led_init_generic -
18184919Sxy150489  * @hw: pointer to the HW structure
18194919Sxy150489  *
18204919Sxy150489  */
18214919Sxy150489 s32
e1000_id_led_init_generic(struct e1000_hw * hw)18224919Sxy150489 e1000_id_led_init_generic(struct e1000_hw *hw)
18234919Sxy150489 {
18244919Sxy150489 	struct e1000_mac_info *mac = &hw->mac;
18254919Sxy150489 	s32 ret_val;
18264919Sxy150489 	const u32 ledctl_mask = 0x000000FF;
18274919Sxy150489 	const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;
18284919Sxy150489 	const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
18294919Sxy150489 	u16 data, i, temp;
18304919Sxy150489 	const u16 led_mask = 0x0F;
18314919Sxy150489 
18324919Sxy150489 	DEBUGFUNC("e1000_id_led_init_generic");
18334919Sxy150489 
18346735Scc210113 	ret_val = hw->nvm.ops.valid_led_default(hw, &data);
18354919Sxy150489 	if (ret_val)
18364919Sxy150489 		goto out;
18374919Sxy150489 
18384919Sxy150489 	mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL);
18394919Sxy150489 	mac->ledctl_mode1 = mac->ledctl_default;
18404919Sxy150489 	mac->ledctl_mode2 = mac->ledctl_default;
18414919Sxy150489 
18424919Sxy150489 	for (i = 0; i < 4; i++) {
18434919Sxy150489 		temp = (data >> (i << 2)) & led_mask;
18444919Sxy150489 		switch (temp) {
18454919Sxy150489 		case ID_LED_ON1_DEF2:
18464919Sxy150489 		case ID_LED_ON1_ON2:
18474919Sxy150489 		case ID_LED_ON1_OFF2:
18484919Sxy150489 			mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
18494919Sxy150489 			mac->ledctl_mode1 |= ledctl_on << (i << 3);
18504919Sxy150489 			break;
18514919Sxy150489 		case ID_LED_OFF1_DEF2:
18524919Sxy150489 		case ID_LED_OFF1_ON2:
18534919Sxy150489 		case ID_LED_OFF1_OFF2:
18544919Sxy150489 			mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
18554919Sxy150489 			mac->ledctl_mode1 |= ledctl_off << (i << 3);
18564919Sxy150489 			break;
18574919Sxy150489 		default:
18584919Sxy150489 			/* Do nothing */
18594919Sxy150489 			break;
18604919Sxy150489 		}
18614919Sxy150489 		switch (temp) {
18624919Sxy150489 		case ID_LED_DEF1_ON2:
18634919Sxy150489 		case ID_LED_ON1_ON2:
18644919Sxy150489 		case ID_LED_OFF1_ON2:
18654919Sxy150489 			mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
18664919Sxy150489 			mac->ledctl_mode2 |= ledctl_on << (i << 3);
18674919Sxy150489 			break;
18684919Sxy150489 		case ID_LED_DEF1_OFF2:
18694919Sxy150489 		case ID_LED_ON1_OFF2:
18704919Sxy150489 		case ID_LED_OFF1_OFF2:
18714919Sxy150489 			mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
18724919Sxy150489 			mac->ledctl_mode2 |= ledctl_off << (i << 3);
18734919Sxy150489 			break;
18744919Sxy150489 		default:
18754919Sxy150489 			/* Do nothing */
18764919Sxy150489 			break;
18774919Sxy150489 		}
18784919Sxy150489 	}
18794919Sxy150489 
18804919Sxy150489 out:
18814919Sxy150489 	return (ret_val);
18824919Sxy150489 }
18834919Sxy150489 
18844919Sxy150489 /*
18854919Sxy150489  * e1000_setup_led_generic - Configures SW controllable LED
18864919Sxy150489  * @hw: pointer to the HW structure
18874919Sxy150489  *
18884919Sxy150489  * This prepares the SW controllable LED for use and saves the current state
18894919Sxy150489  * of the LED so it can be later restored.
18904919Sxy150489  */
18914919Sxy150489 s32
e1000_setup_led_generic(struct e1000_hw * hw)18924919Sxy150489 e1000_setup_led_generic(struct e1000_hw *hw)
18934919Sxy150489 {
18944919Sxy150489 	u32 ledctl;
18954919Sxy150489 	s32 ret_val = E1000_SUCCESS;
18964919Sxy150489 
18974919Sxy150489 	DEBUGFUNC("e1000_setup_led_generic");
18984919Sxy150489 
18996735Scc210113 	if (hw->mac.ops.setup_led != e1000_setup_led_generic) {
19004919Sxy150489 		ret_val = -E1000_ERR_CONFIG;
19014919Sxy150489 		goto out;
19024919Sxy150489 	}
19034919Sxy150489 
19046735Scc210113 	if (hw->phy.media_type == e1000_media_type_fiber) {
19054919Sxy150489 		ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
19064919Sxy150489 		hw->mac.ledctl_default = ledctl;
19074919Sxy150489 		/* Turn off LED0 */
19084919Sxy150489 		ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
19094919Sxy150489 		    E1000_LEDCTL_LED0_BLINK |
19104919Sxy150489 		    E1000_LEDCTL_LED0_MODE_MASK);
19114919Sxy150489 		ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
19124919Sxy150489 		    E1000_LEDCTL_LED0_MODE_SHIFT);
19134919Sxy150489 		E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
19146735Scc210113 	} else if (hw->phy.media_type == e1000_media_type_copper) {
19154919Sxy150489 		E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
19164919Sxy150489 	}
19174919Sxy150489 
19184919Sxy150489 out:
19194919Sxy150489 	return (ret_val);
19204919Sxy150489 }
19214919Sxy150489 
19224919Sxy150489 /*
19234919Sxy150489  * e1000_cleanup_led_generic - Set LED config to default operation
19244919Sxy150489  * @hw: pointer to the HW structure
19254919Sxy150489  *
19264919Sxy150489  * Remove the current LED configuration and set the LED configuration
19274919Sxy150489  * to the default value, saved from the EEPROM.
19284919Sxy150489  */
19294919Sxy150489 s32
e1000_cleanup_led_generic(struct e1000_hw * hw)19304919Sxy150489 e1000_cleanup_led_generic(struct e1000_hw *hw)
19314919Sxy150489 {
19324919Sxy150489 	s32 ret_val = E1000_SUCCESS;
19334919Sxy150489 
19344919Sxy150489 	DEBUGFUNC("e1000_cleanup_led_generic");
19354919Sxy150489 
19366735Scc210113 	if (hw->mac.ops.cleanup_led != e1000_cleanup_led_generic) {
19374919Sxy150489 		ret_val = -E1000_ERR_CONFIG;
19384919Sxy150489 		goto out;
19394919Sxy150489 	}
19404919Sxy150489 
19414919Sxy150489 	E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default);
19424919Sxy150489 
19434919Sxy150489 out:
19444919Sxy150489 	return (ret_val);
19454919Sxy150489 }
19464919Sxy150489 
19474919Sxy150489 /*
19484919Sxy150489  * e1000_blink_led_generic - Blink LED
19494919Sxy150489  * @hw: pointer to the HW structure
19504919Sxy150489  *
19516735Scc210113  * Blink the LEDs which are set to be on.
19524919Sxy150489  */
19534919Sxy150489 s32
e1000_blink_led_generic(struct e1000_hw * hw)19544919Sxy150489 e1000_blink_led_generic(struct e1000_hw *hw)
19554919Sxy150489 {
19564919Sxy150489 	u32 ledctl_blink = 0;
19574919Sxy150489 	u32 i;
19584919Sxy150489 
19594919Sxy150489 	DEBUGFUNC("e1000_blink_led_generic");
19604919Sxy150489 
19616735Scc210113 	if (hw->phy.media_type == e1000_media_type_fiber) {
19624919Sxy150489 		/* always blink LED0 for PCI-E fiber */
19634919Sxy150489 		ledctl_blink = E1000_LEDCTL_LED0_BLINK |
19644919Sxy150489 		    (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
19654919Sxy150489 	} else {
19664919Sxy150489 		/*
19674919Sxy150489 		 * set the blink bit for each LED that's "on" (0x0E)
19684919Sxy150489 		 * in ledctl_mode2
19694919Sxy150489 		 */
19704919Sxy150489 		ledctl_blink = hw->mac.ledctl_mode2;
19714919Sxy150489 		for (i = 0; i < 4; i++)
19724919Sxy150489 			if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
19734919Sxy150489 			    E1000_LEDCTL_MODE_LED_ON)
19744919Sxy150489 				ledctl_blink |= (E1000_LEDCTL_LED0_BLINK <<
19754919Sxy150489 				    (i * 8));
19764919Sxy150489 	}
19774919Sxy150489 
19784919Sxy150489 	E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl_blink);
19794919Sxy150489 
19804919Sxy150489 	return (E1000_SUCCESS);
19814919Sxy150489 }
19824919Sxy150489 
19834919Sxy150489 /*
19844919Sxy150489  * e1000_led_on_generic - Turn LED on
19854919Sxy150489  * @hw: pointer to the HW structure
19864919Sxy150489  *
19874919Sxy150489  * Turn LED on.
19884919Sxy150489  */
19894919Sxy150489 s32
e1000_led_on_generic(struct e1000_hw * hw)19904919Sxy150489 e1000_led_on_generic(struct e1000_hw *hw)
19914919Sxy150489 {
19924919Sxy150489 	u32 ctrl;
19934919Sxy150489 
19944919Sxy150489 	DEBUGFUNC("e1000_led_on_generic");
19954919Sxy150489 
19966735Scc210113 	switch (hw->phy.media_type) {
19974919Sxy150489 	case e1000_media_type_fiber:
19984919Sxy150489 		ctrl = E1000_READ_REG(hw, E1000_CTRL);
19994919Sxy150489 		ctrl &= ~E1000_CTRL_SWDPIN0;
20004919Sxy150489 		ctrl |= E1000_CTRL_SWDPIO0;
20014919Sxy150489 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
20024919Sxy150489 		break;
20034919Sxy150489 	case e1000_media_type_copper:
20044919Sxy150489 		E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2);
20054919Sxy150489 		break;
20064919Sxy150489 	default:
20074919Sxy150489 		break;
20084919Sxy150489 	}
20094919Sxy150489 
20104919Sxy150489 	return (E1000_SUCCESS);
20114919Sxy150489 }
20124919Sxy150489 
20134919Sxy150489 /*
20144919Sxy150489  * e1000_led_off_generic - Turn LED off
20154919Sxy150489  * @hw: pointer to the HW structure
20164919Sxy150489  *
20174919Sxy150489  * Turn LED off.
20184919Sxy150489  */
20194919Sxy150489 s32
e1000_led_off_generic(struct e1000_hw * hw)20204919Sxy150489 e1000_led_off_generic(struct e1000_hw *hw)
20214919Sxy150489 {
20224919Sxy150489 	u32 ctrl;
20234919Sxy150489 
20244919Sxy150489 	DEBUGFUNC("e1000_led_off_generic");
20254919Sxy150489 
20266735Scc210113 	switch (hw->phy.media_type) {
20274919Sxy150489 	case e1000_media_type_fiber:
20284919Sxy150489 		ctrl = E1000_READ_REG(hw, E1000_CTRL);
20294919Sxy150489 		ctrl |= E1000_CTRL_SWDPIN0;
20304919Sxy150489 		ctrl |= E1000_CTRL_SWDPIO0;
20314919Sxy150489 		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
20324919Sxy150489 		break;
20334919Sxy150489 	case e1000_media_type_copper:
20344919Sxy150489 		E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
20354919Sxy150489 		break;
20364919Sxy150489 	default:
20374919Sxy150489 		break;
20384919Sxy150489 	}
20394919Sxy150489 
20404919Sxy150489 	return (E1000_SUCCESS);
20414919Sxy150489 }
20424919Sxy150489 
20434919Sxy150489 /*
20444919Sxy150489  * e1000_set_pcie_no_snoop_generic - Set PCI-express capabilities
20454919Sxy150489  * @hw: pointer to the HW structure
20464919Sxy150489  * @no_snoop: bitmap of snoop events
20474919Sxy150489  *
20484919Sxy150489  * Set the PCI-express register to snoop for events enabled in 'no_snoop'.
20494919Sxy150489  */
20504919Sxy150489 void
e1000_set_pcie_no_snoop_generic(struct e1000_hw * hw,u32 no_snoop)20514919Sxy150489 e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop)
20524919Sxy150489 {
20534919Sxy150489 	u32 gcr;
20544919Sxy150489 
20554919Sxy150489 	DEBUGFUNC("e1000_set_pcie_no_snoop_generic");
20564919Sxy150489 
20574919Sxy150489 	if (hw->bus.type != e1000_bus_type_pci_express)
20584919Sxy150489 		return;
20594919Sxy150489 
20604919Sxy150489 	if (no_snoop) {
20614919Sxy150489 		gcr = E1000_READ_REG(hw, E1000_GCR);
20624919Sxy150489 		gcr &= ~(PCIE_NO_SNOOP_ALL);
20634919Sxy150489 		gcr |= no_snoop;
20644919Sxy150489 		E1000_WRITE_REG(hw, E1000_GCR, gcr);
20654919Sxy150489 	}
20664919Sxy150489 }
20674919Sxy150489 
20684919Sxy150489 /*
20694919Sxy150489  * e1000_disable_pcie_master_generic - Disables PCI-express master access
20704919Sxy150489  * @hw: pointer to the HW structure
20714919Sxy150489  *
20724919Sxy150489  * Returns 0 (E1000_SUCCESS) if successful, else returns -10
20736735Scc210113  * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused
20744919Sxy150489  * the master requests to be disabled.
20754919Sxy150489  *
20764919Sxy150489  * Disables PCI-Express master access and verifies there are no pending
20774919Sxy150489  * requests.
20784919Sxy150489  */
20794919Sxy150489 s32
e1000_disable_pcie_master_generic(struct e1000_hw * hw)20804919Sxy150489 e1000_disable_pcie_master_generic(struct e1000_hw *hw)
20814919Sxy150489 {
20824919Sxy150489 	u32 ctrl;
20834919Sxy150489 	s32 timeout = MASTER_DISABLE_TIMEOUT;
20844919Sxy150489 	s32 ret_val = E1000_SUCCESS;
20854919Sxy150489 
20864919Sxy150489 	DEBUGFUNC("e1000_disable_pcie_master_generic");
20874919Sxy150489 
20884919Sxy150489 	if (hw->bus.type != e1000_bus_type_pci_express)
20894919Sxy150489 		goto out;
20904919Sxy150489 
20914919Sxy150489 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
20924919Sxy150489 	ctrl |= E1000_CTRL_GIO_MASTER_DISABLE;
20934919Sxy150489 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
20944919Sxy150489 
20954919Sxy150489 	while (timeout) {
20964919Sxy150489 		if (!(E1000_READ_REG(hw, E1000_STATUS) &
20974919Sxy150489 		    E1000_STATUS_GIO_MASTER_ENABLE))
20984919Sxy150489 			break;
20994919Sxy150489 		usec_delay(100);
21004919Sxy150489 		timeout--;
21014919Sxy150489 	}
21024919Sxy150489 
21034919Sxy150489 	if (!timeout) {
21044919Sxy150489 		DEBUGOUT("Master requests are pending.\n");
21054919Sxy150489 		ret_val = -E1000_ERR_MASTER_REQUESTS_PENDING;
21064919Sxy150489 		goto out;
21074919Sxy150489 	}
21084919Sxy150489 
21094919Sxy150489 out:
21104919Sxy150489 	return (ret_val);
21114919Sxy150489 }
21124919Sxy150489 
21134919Sxy150489 /*
21144919Sxy150489  * e1000_reset_adaptive_generic - Reset Adaptive Interframe Spacing
21154919Sxy150489  * @hw: pointer to the HW structure
21164919Sxy150489  *
21174919Sxy150489  * Reset the Adaptive Interframe Spacing throttle to default values.
21184919Sxy150489  */
21194919Sxy150489 void
e1000_reset_adaptive_generic(struct e1000_hw * hw)21204919Sxy150489 e1000_reset_adaptive_generic(struct e1000_hw *hw)
21214919Sxy150489 {
21224919Sxy150489 	struct e1000_mac_info *mac = &hw->mac;
21234919Sxy150489 
21244919Sxy150489 	DEBUGFUNC("e1000_reset_adaptive_generic");
21254919Sxy150489 
21264919Sxy150489 	if (!mac->adaptive_ifs) {
21274919Sxy150489 		DEBUGOUT("Not in Adaptive IFS mode!\n");
21284919Sxy150489 		return;
21294919Sxy150489 	}
21304919Sxy150489 
21318479SChenlu.Chen@Sun.COM 	mac->current_ifs_val = 0;
21328479SChenlu.Chen@Sun.COM 	mac->ifs_min_val = IFS_MIN;
21338479SChenlu.Chen@Sun.COM 	mac->ifs_max_val = IFS_MAX;
21348479SChenlu.Chen@Sun.COM 	mac->ifs_step_size = IFS_STEP;
21358479SChenlu.Chen@Sun.COM 	mac->ifs_ratio = IFS_RATIO;
21364919Sxy150489 
21377607STed.You@Sun.COM 	mac->in_ifs_mode = false;
21384919Sxy150489 	E1000_WRITE_REG(hw, E1000_AIT, 0);
21394919Sxy150489 }
21404919Sxy150489 
21414919Sxy150489 /*
21424919Sxy150489  * e1000_update_adaptive_generic - Update Adaptive Interframe Spacing
21434919Sxy150489  * @hw: pointer to the HW structure
21444919Sxy150489  *
21454919Sxy150489  * Update the Adaptive Interframe Spacing Throttle value based on the
21464919Sxy150489  * time between transmitted packets and time between collisions.
21474919Sxy150489  */
21484919Sxy150489 void
e1000_update_adaptive_generic(struct e1000_hw * hw)21494919Sxy150489 e1000_update_adaptive_generic(struct e1000_hw *hw)
21504919Sxy150489 {
21514919Sxy150489 	struct e1000_mac_info *mac = &hw->mac;
21524919Sxy150489 
21534919Sxy150489 	DEBUGFUNC("e1000_update_adaptive_generic");
21544919Sxy150489 
21554919Sxy150489 	if (!mac->adaptive_ifs) {
21564919Sxy150489 		DEBUGOUT("Not in Adaptive IFS mode!\n");
21574919Sxy150489 		return;
21584919Sxy150489 	}
21594919Sxy150489 
21604919Sxy150489 	if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) {
21614919Sxy150489 		if (mac->tx_packet_delta > MIN_NUM_XMITS) {
21627607STed.You@Sun.COM 			mac->in_ifs_mode = true;
21634919Sxy150489 			if (mac->current_ifs_val < mac->ifs_max_val) {
21644919Sxy150489 				if (!mac->current_ifs_val)
21654919Sxy150489 					mac->current_ifs_val = mac->ifs_min_val;
21664919Sxy150489 				else
21674919Sxy150489 					mac->current_ifs_val +=
21684919Sxy150489 					    mac->ifs_step_size;
21694919Sxy150489 				E1000_WRITE_REG(hw, E1000_AIT,
21704919Sxy150489 				    mac->current_ifs_val);
21714919Sxy150489 			}
21724919Sxy150489 		}
21734919Sxy150489 	} else {
21744919Sxy150489 		if (mac->in_ifs_mode &&
21754919Sxy150489 		    (mac->tx_packet_delta <= MIN_NUM_XMITS)) {
21764919Sxy150489 			mac->current_ifs_val = 0;
21777607STed.You@Sun.COM 			mac->in_ifs_mode = false;
21784919Sxy150489 			E1000_WRITE_REG(hw, E1000_AIT, 0);
21794919Sxy150489 		}
21804919Sxy150489 	}
21814919Sxy150489 }
21824919Sxy150489 
21834919Sxy150489 /*
21844919Sxy150489  * e1000_validate_mdi_setting_generic - Verify MDI/MDIx settings
21854919Sxy150489  * @hw: pointer to the HW structure
21864919Sxy150489  *
21876735Scc210113  * Verify that when not using auto-negotiation that MDI/MDIx is correctly
21884919Sxy150489  * set, which is forced to MDI mode only.
21894919Sxy150489  */
219011020SMin.Xu@Sun.COM static s32
e1000_validate_mdi_setting_generic(struct e1000_hw * hw)21914919Sxy150489 e1000_validate_mdi_setting_generic(struct e1000_hw *hw)
21924919Sxy150489 {
21934919Sxy150489 	s32 ret_val = E1000_SUCCESS;
21944919Sxy150489 
21954919Sxy150489 	DEBUGFUNC("e1000_validate_mdi_setting_generic");
21964919Sxy150489 
21974919Sxy150489 	if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) {
21984919Sxy150489 		DEBUGOUT("Invalid MDI setting detected\n");
21994919Sxy150489 		hw->phy.mdix = 1;
22004919Sxy150489 		ret_val = -E1000_ERR_CONFIG;
22014919Sxy150489 		goto out;
22024919Sxy150489 	}
22034919Sxy150489 
22044919Sxy150489 out:
22054919Sxy150489 	return (ret_val);
22064919Sxy150489 }
2207