/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright(c) 2001-2020 Intel Corporation
 */

/*
 * 82543GC Gigabit Ethernet Controller (Fiber)
 * 82543GC Gigabit Ethernet Controller (Copper)
 * 82544EI Gigabit Ethernet Controller (Copper)
 * 82544EI Gigabit Ethernet Controller (Fiber)
 * 82544GC Gigabit Ethernet Controller (Copper)
 * 82544GC Gigabit Ethernet Controller (LOM)
 */

#include "e1000_api.h"

STATIC s32  e1000_init_phy_params_82543(struct e1000_hw *hw);
STATIC s32  e1000_init_nvm_params_82543(struct e1000_hw *hw);
STATIC s32  e1000_init_mac_params_82543(struct e1000_hw *hw);
STATIC s32  e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset,
				     u16 *data);
STATIC s32  e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset,
				      u16 data);
STATIC s32  e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw);
STATIC s32  e1000_phy_hw_reset_82543(struct e1000_hw *hw);
STATIC s32  e1000_reset_hw_82543(struct e1000_hw *hw);
STATIC s32  e1000_init_hw_82543(struct e1000_hw *hw);
STATIC s32  e1000_setup_link_82543(struct e1000_hw *hw);
STATIC s32  e1000_setup_copper_link_82543(struct e1000_hw *hw);
STATIC s32  e1000_setup_fiber_link_82543(struct e1000_hw *hw);
STATIC s32  e1000_check_for_copper_link_82543(struct e1000_hw *hw);
STATIC s32  e1000_check_for_fiber_link_82543(struct e1000_hw *hw);
STATIC s32  e1000_led_on_82543(struct e1000_hw *hw);
STATIC s32  e1000_led_off_82543(struct e1000_hw *hw);
STATIC void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset,
				   u32 value);
STATIC void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw);
STATIC s32  e1000_config_mac_to_phy_82543(struct e1000_hw *hw);
STATIC bool e1000_init_phy_disabled_82543(struct e1000_hw *hw);
STATIC void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl);
STATIC s32  e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw);
STATIC void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl);
STATIC u16  e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw);
STATIC void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
					   u16 count);
STATIC bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw);
STATIC void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state);

/**
 *  e1000_init_phy_params_82543 - Init PHY func ptrs.
 *  @hw: pointer to the HW structure
 **/
STATIC s32 e1000_init_phy_params_82543(struct e1000_hw *hw)
{
	struct e1000_phy_info *phy = &hw->phy;
	s32 ret_val = E1000_SUCCESS;

	DEBUGFUNC("e1000_init_phy_params_82543");

	if (hw->phy.media_type != e1000_media_type_copper) {
		phy->type = e1000_phy_none;
		goto out;
	} else {
		phy->ops.power_up = e1000_power_up_phy_copper;
		phy->ops.power_down = e1000_power_down_phy_copper;
	}

	phy->addr		= 1;
	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
	phy->reset_delay_us	= 10000;
	phy->type		= e1000_phy_m88;

	/* Function Pointers */
	phy->ops.check_polarity	= e1000_check_polarity_m88;
	phy->ops.commit		= e1000_phy_sw_reset_generic;
	phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82543;
	phy->ops.get_cable_length = e1000_get_cable_length_m88;
	phy->ops.get_cfg_done	= e1000_get_cfg_done_generic;
	phy->ops.read_reg	= (hw->mac.type == e1000_82543)
				  ? e1000_read_phy_reg_82543
				  : e1000_read_phy_reg_m88;
	phy->ops.reset		= (hw->mac.type == e1000_82543)
				  ? e1000_phy_hw_reset_82543
				  : e1000_phy_hw_reset_generic;
	phy->ops.write_reg	= (hw->mac.type == e1000_82543)
				  ? e1000_write_phy_reg_82543
				  : e1000_write_phy_reg_m88;
	phy->ops.get_info	= e1000_get_phy_info_m88;

	/*
	 * The external PHY of the 82543 can be in a funky state.
	 * Resetting helps us read the PHY registers for acquiring
	 * the PHY ID.
	 */
	if (!e1000_init_phy_disabled_82543(hw)) {
		ret_val = phy->ops.reset(hw);
		if (ret_val) {
			DEBUGOUT("Resetting PHY during init failed.\n");
			goto out;
		}
		msec_delay(20);
	}

	ret_val = e1000_get_phy_id(hw);
	if (ret_val)
		goto out;

	/* Verify phy id */
	switch (hw->mac.type) {
	case e1000_82543:
		if (phy->id != M88E1000_E_PHY_ID) {
			ret_val = -E1000_ERR_PHY;
			goto out;
		}
		break;
	case e1000_82544:
		if (phy->id != M88E1000_I_PHY_ID) {
			ret_val = -E1000_ERR_PHY;
			goto out;
		}
		break;
	default:
		ret_val = -E1000_ERR_PHY;
		goto out;
		break;
	}

out:
	return ret_val;
}

/**
 *  e1000_init_nvm_params_82543 - Init NVM func ptrs.
 *  @hw: pointer to the HW structure
 **/
STATIC s32 e1000_init_nvm_params_82543(struct e1000_hw *hw)
{
	struct e1000_nvm_info *nvm = &hw->nvm;

	DEBUGFUNC("e1000_init_nvm_params_82543");

	nvm->type		= e1000_nvm_eeprom_microwire;
	nvm->word_size		= 64;
	nvm->delay_usec		= 50;
	nvm->address_bits	=  6;
	nvm->opcode_bits	=  3;

	/* Function Pointers */
	nvm->ops.read		= e1000_read_nvm_microwire;
	nvm->ops.update		= e1000_update_nvm_checksum_generic;
	nvm->ops.valid_led_default = e1000_valid_led_default_generic;
	nvm->ops.validate	= e1000_validate_nvm_checksum_generic;
	nvm->ops.write		= e1000_write_nvm_microwire;

	return E1000_SUCCESS;
}

/**
 *  e1000_init_mac_params_82543 - Init MAC func ptrs.
 *  @hw: pointer to the HW structure
 **/
STATIC s32 e1000_init_mac_params_82543(struct e1000_hw *hw)
{
	struct e1000_mac_info *mac = &hw->mac;

	DEBUGFUNC("e1000_init_mac_params_82543");

	/* Set media type */
	switch (hw->device_id) {
	case E1000_DEV_ID_82543GC_FIBER:
	case E1000_DEV_ID_82544EI_FIBER:
		hw->phy.media_type = e1000_media_type_fiber;
		break;
	default:
		hw->phy.media_type = e1000_media_type_copper;
		break;
	}

	/* Set mta register count */
	mac->mta_reg_count = 128;
	/* Set rar entry count */
	mac->rar_entry_count = E1000_RAR_ENTRIES;

	/* Function pointers */

	/* bus type/speed/width */
	mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
	/* function id */
	mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci;
	/* reset */
	mac->ops.reset_hw = e1000_reset_hw_82543;
	/* hw initialization */
	mac->ops.init_hw = e1000_init_hw_82543;
	/* link setup */
	mac->ops.setup_link = e1000_setup_link_82543;
	/* physical interface setup */
	mac->ops.setup_physical_interface =
		(hw->phy.media_type == e1000_media_type_copper)
		 ? e1000_setup_copper_link_82543 : e1000_setup_fiber_link_82543;
	/* check for link */
	mac->ops.check_for_link =
		(hw->phy.media_type == e1000_media_type_copper)
		 ? e1000_check_for_copper_link_82543
		 : e1000_check_for_fiber_link_82543;
	/* link info */
	mac->ops.get_link_up_info =
		(hw->phy.media_type == e1000_media_type_copper)
		 ? e1000_get_speed_and_duplex_copper_generic
		 : e1000_get_speed_and_duplex_fiber_serdes_generic;
	/* multicast address update */
	mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
	/* writing VFTA */
	mac->ops.write_vfta = e1000_write_vfta_82543;
	/* clearing VFTA */
	mac->ops.clear_vfta = e1000_clear_vfta_generic;
	/* turn on/off LED */
	mac->ops.led_on = e1000_led_on_82543;
	mac->ops.led_off = e1000_led_off_82543;
	/* clear hardware counters */
	mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82543;

	/* Set tbi compatibility */
	if ((hw->mac.type != e1000_82543) ||
	    (hw->phy.media_type == e1000_media_type_fiber))
		e1000_set_tbi_compatibility_82543(hw, false);

	return E1000_SUCCESS;
}

/**
 *  e1000_init_function_pointers_82543 - Init func ptrs.
 *  @hw: pointer to the HW structure
 *
 *  Called to initialize all function pointers and parameters.
 **/
void e1000_init_function_pointers_82543(struct e1000_hw *hw)
{
	DEBUGFUNC("e1000_init_function_pointers_82543");

	hw->mac.ops.init_params = e1000_init_mac_params_82543;
	hw->nvm.ops.init_params = e1000_init_nvm_params_82543;
	hw->phy.ops.init_params = e1000_init_phy_params_82543;
}

/**
 *  e1000_tbi_compatibility_enabled_82543 - Returns TBI compat status
 *  @hw: pointer to the HW structure
 *
 *  Returns the current status of 10-bit Interface (TBI) compatibility
 *  (enabled/disabled).
 **/
STATIC bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw)
{
	struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
	bool state = false;

	DEBUGFUNC("e1000_tbi_compatibility_enabled_82543");

	if (hw->mac.type != e1000_82543) {
		DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
		goto out;
	}

	state = !!(dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED);

out:
	return state;
}

/**
 *  e1000_set_tbi_compatibility_82543 - Set TBI compatibility
 *  @hw: pointer to the HW structure
 *  @state: enable/disable TBI compatibility
 *
 *  Enables or disabled 10-bit Interface (TBI) compatibility.
 **/
void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state)
{
	struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;

	DEBUGFUNC("e1000_set_tbi_compatibility_82543");

	if (hw->mac.type != e1000_82543) {
		DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
		goto out;
	}

	if (state)
		dev_spec->tbi_compatibility |= TBI_COMPAT_ENABLED;
	else
		dev_spec->tbi_compatibility &= ~TBI_COMPAT_ENABLED;

out:
	return;
}

/**
 *  e1000_tbi_sbp_enabled_82543 - Returns TBI SBP status
 *  @hw: pointer to the HW structure
 *
 *  Returns the current status of 10-bit Interface (TBI) store bad packet (SBP)
 *  (enabled/disabled).
 **/
bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw)
{
	struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
	bool state = false;

	DEBUGFUNC("e1000_tbi_sbp_enabled_82543");

	if (hw->mac.type != e1000_82543) {
		DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
		goto out;
	}

	state = !!(dev_spec->tbi_compatibility & TBI_SBP_ENABLED);

out:
	return state;
}

/**
 *  e1000_set_tbi_sbp_82543 - Set TBI SBP
 *  @hw: pointer to the HW structure
 *  @state: enable/disable TBI store bad packet
 *
 *  Enables or disabled 10-bit Interface (TBI) store bad packet (SBP).
 **/
STATIC void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state)
{
	struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;

	DEBUGFUNC("e1000_set_tbi_sbp_82543");

	if (state && e1000_tbi_compatibility_enabled_82543(hw))
		dev_spec->tbi_compatibility |= TBI_SBP_ENABLED;
	else
		dev_spec->tbi_compatibility &= ~TBI_SBP_ENABLED;

	return;
}

/**
 *  e1000_init_phy_disabled_82543 - Returns init PHY status
 *  @hw: pointer to the HW structure
 *
 *  Returns the current status of whether PHY initialization is disabled.
 *  True if PHY initialization is disabled else false.
 **/
STATIC bool e1000_init_phy_disabled_82543(struct e1000_hw *hw)
{
	struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
	bool ret_val;

	DEBUGFUNC("e1000_init_phy_disabled_82543");

	if (hw->mac.type != e1000_82543) {
		ret_val = false;
		goto out;
	}

	ret_val = dev_spec->init_phy_disabled;

out:
	return ret_val;
}

/**
 *  e1000_tbi_adjust_stats_82543 - Adjust stats when TBI enabled
 *  @hw: pointer to the HW structure
 *  @stats: Struct containing statistic register values
 *  @frame_len: The length of the frame in question
 *  @mac_addr: The Ethernet destination address of the frame in question
 *  @max_frame_size: The maximum frame size
 *
 *  Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
 **/
void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw,
				  struct e1000_hw_stats *stats, u32 frame_len,
				  u8 *mac_addr, u32 max_frame_size)
{
	if (!(e1000_tbi_sbp_enabled_82543(hw)))
		goto out;

	/* First adjust the frame length. */
	frame_len--;
	/*
	 * We need to adjust the statistics counters, since the hardware
	 * counters overcount this packet as a CRC error and undercount
	 * the packet as a good packet
	 */
	/* This packet should not be counted as a CRC error. */
	stats->crcerrs--;
	/* This packet does count as a Good Packet Received. */
	stats->gprc++;

	/* Adjust the Good Octets received counters */
	stats->gorc += frame_len;

	/*
	 * Is this a broadcast or multicast?  Check broadcast first,
	 * since the test for a multicast frame will test positive on
	 * a broadcast frame.
	 */
	if ((mac_addr[0] == 0xff) && (mac_addr[1] == 0xff))
		/* Broadcast packet */
		stats->bprc++;
	else if (*mac_addr & 0x01)
		/* Multicast packet */
		stats->mprc++;

	/*
	 * In this case, the hardware has over counted the number of
	 * oversize frames.
	 */
	if ((frame_len == max_frame_size) && (stats->roc > 0))
		stats->roc--;

	/*
	 * Adjust the bin counters when the extra byte put the frame in the
	 * wrong bin. Remember that the frame_len was adjusted above.
	 */
	if (frame_len == 64) {
		stats->prc64++;
		stats->prc127--;
	} else if (frame_len == 127) {
		stats->prc127++;
		stats->prc255--;
	} else if (frame_len == 255) {
		stats->prc255++;
		stats->prc511--;
	} else if (frame_len == 511) {
		stats->prc511++;
		stats->prc1023--;
	} else if (frame_len == 1023) {
		stats->prc1023++;
		stats->prc1522--;
	} else if (frame_len == 1522) {
		stats->prc1522++;
	}

out:
	return;
}

/**
 *  e1000_read_phy_reg_82543 - Read PHY register
 *  @hw: pointer to the HW structure
 *  @offset: register offset to be read
 *  @data: pointer to the read data
 *
 *  Reads the PHY at offset and stores the information read to data.
 **/
STATIC s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 *data)
{
	u32 mdic;
	s32 ret_val = E1000_SUCCESS;

	DEBUGFUNC("e1000_read_phy_reg_82543");

	if (offset > MAX_PHY_REG_ADDRESS) {
		DEBUGOUT1("PHY Address %d is out of range\n", offset);
		ret_val = -E1000_ERR_PARAM;
		goto out;
	}

	/*
	 * We must first send a preamble through the MDIO pin to signal the
	 * beginning of an MII instruction.  This is done by sending 32
	 * consecutive "1" bits.
	 */
	e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);

	/*
	 * Now combine the next few fields that are required for a read
	 * operation.  We use this method instead of calling the
	 * e1000_shift_out_mdi_bits routine five different times.  The format
	 * of an MII read instruction consists of a shift out of 14 bits and
	 * is defined as follows:
	 *         <Preamble><SOF><Op Code><Phy Addr><Offset>
	 * followed by a shift in of 18 bits.  This first two bits shifted in
	 * are TurnAround bits used to avoid contention on the MDIO pin when a
	 * READ operation is performed.  These two bits are thrown away
	 * followed by a shift in of 16 bits which contains the desired data.
	 */
	mdic = (offset | (hw->phy.addr << 5) |
		(PHY_OP_READ << 10) | (PHY_SOF << 12));

	e1000_shift_out_mdi_bits_82543(hw, mdic, 14);

	/*
	 * Now that we've shifted out the read command to the MII, we need to
	 * "shift in" the 16-bit value (18 total bits) of the requested PHY
	 * register address.
	 */
	*data = e1000_shift_in_mdi_bits_82543(hw);

out:
	return ret_val;
}

/**
 *  e1000_write_phy_reg_82543 - Write PHY register
 *  @hw: pointer to the HW structure
 *  @offset: register offset to be written
 *  @data: pointer to the data to be written at offset
 *
 *  Writes data to the PHY at offset.
 **/
STATIC s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 data)
{
	u32 mdic;
	s32 ret_val = E1000_SUCCESS;

	DEBUGFUNC("e1000_write_phy_reg_82543");

	if (offset > MAX_PHY_REG_ADDRESS) {
		DEBUGOUT1("PHY Address %d is out of range\n", offset);
		ret_val = -E1000_ERR_PARAM;
		goto out;
	}

	/*
	 * We'll need to use the SW defined pins to shift the write command
	 * out to the PHY. We first send a preamble to the PHY to signal the
	 * beginning of the MII instruction.  This is done by sending 32
	 * consecutive "1" bits.
	 */
	e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);

	/*
	 * Now combine the remaining required fields that will indicate a
	 * write operation. We use this method instead of calling the
	 * e1000_shift_out_mdi_bits routine for each field in the command. The
	 * format of a MII write instruction is as follows:
	 * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
	 */
	mdic = ((PHY_TURNAROUND) | (offset << 2) | (hw->phy.addr << 7) |
		(PHY_OP_WRITE << 12) | (PHY_SOF << 14));
	mdic <<= 16;
	mdic |= (u32)data;

	e1000_shift_out_mdi_bits_82543(hw, mdic, 32);

out:
	return ret_val;
}

/**
 *  e1000_raise_mdi_clk_82543 - Raise Management Data Input clock
 *  @hw: pointer to the HW structure
 *  @ctrl: pointer to the control register
 *
 *  Raise the management data input clock by setting the MDC bit in the control
 *  register.
 **/
STATIC void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
{
	/*
	 * Raise the clock input to the Management Data Clock (by setting the
	 * MDC bit), and then delay a sufficient amount of time.
	 */
	E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl | E1000_CTRL_MDC));
	E1000_WRITE_FLUSH(hw);
	usec_delay(10);
}

/**
 *  e1000_lower_mdi_clk_82543 - Lower Management Data Input clock
 *  @hw: pointer to the HW structure
 *  @ctrl: pointer to the control register
 *
 *  Lower the management data input clock by clearing the MDC bit in the
 *  control register.
 **/
STATIC void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
{
	/*
	 * Lower the clock input to the Management Data Clock (by clearing the
	 * MDC bit), and then delay a sufficient amount of time.
	 */
	E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl & ~E1000_CTRL_MDC));
	E1000_WRITE_FLUSH(hw);
	usec_delay(10);
}

/**
 *  e1000_shift_out_mdi_bits_82543 - Shift data bits our to the PHY
 *  @hw: pointer to the HW structure
 *  @data: data to send to the PHY
 *  @count: number of bits to shift out
 *
 *  We need to shift 'count' bits out to the PHY.  So, the value in the
 *  "data" parameter will be shifted out to the PHY one bit at a time.
 *  In order to do this, "data" must be broken down into bits.
 **/
STATIC void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
					   u16 count)
{
	u32 ctrl, mask;

	/*
	 * We need to shift "count" number of bits out to the PHY.  So, the
	 * value in the "data" parameter will be shifted out to the PHY one
	 * bit at a time.  In order to do this, "data" must be broken down
	 * into bits.
	 */
	mask = 0x01;
	mask <<= (count - 1);

	ctrl = E1000_READ_REG(hw, E1000_CTRL);

	/* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
	ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);

	while (mask) {
		/*
		 * A "1" is shifted out to the PHY by setting the MDIO bit to
		 * "1" and then raising and lowering the Management Data Clock.
		 * A "0" is shifted out to the PHY by setting the MDIO bit to
		 * "0" and then raising and lowering the clock.
		 */
		if (data & mask)
			ctrl |= E1000_CTRL_MDIO;
		else
			ctrl &= ~E1000_CTRL_MDIO;

		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
		E1000_WRITE_FLUSH(hw);

		usec_delay(10);

		e1000_raise_mdi_clk_82543(hw, &ctrl);
		e1000_lower_mdi_clk_82543(hw, &ctrl);

		mask >>= 1;
	}
}

/**
 *  e1000_shift_in_mdi_bits_82543 - Shift data bits in from the PHY
 *  @hw: pointer to the HW structure
 *
 *  In order to read a register from the PHY, we need to shift 18 bits
 *  in from the PHY.  Bits are "shifted in" by raising the clock input to
 *  the PHY (setting the MDC bit), and then reading the value of the data out
 *  MDIO bit.
 **/
STATIC u16 e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw)
{
	u32 ctrl;
	u16 data = 0;
	u8 i;

	/*
	 * In order to read a register from the PHY, we need to shift in a
	 * total of 18 bits from the PHY.  The first two bit (turnaround)
	 * times are used to avoid contention on the MDIO pin when a read
	 * operation is performed.  These two bits are ignored by us and
	 * thrown away.  Bits are "shifted in" by raising the input to the
	 * Management Data Clock (setting the MDC bit) and then reading the
	 * value of the MDIO bit.
	 */
	ctrl = E1000_READ_REG(hw, E1000_CTRL);

	/*
	 * Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as
	 * input.
	 */
	ctrl &= ~E1000_CTRL_MDIO_DIR;
	ctrl &= ~E1000_CTRL_MDIO;

	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
	E1000_WRITE_FLUSH(hw);

	/*
	 * Raise and lower the clock before reading in the data.  This accounts
	 * for the turnaround bits.  The first clock occurred when we clocked
	 * out the last bit of the Register Address.
	 */
	e1000_raise_mdi_clk_82543(hw, &ctrl);
	e1000_lower_mdi_clk_82543(hw, &ctrl);

	for (data = 0, i = 0; i < 16; i++) {
		data <<= 1;
		e1000_raise_mdi_clk_82543(hw, &ctrl);
		ctrl = E1000_READ_REG(hw, E1000_CTRL);
		/* Check to see if we shifted in a "1". */
		if (ctrl & E1000_CTRL_MDIO)
			data |= 1;
		e1000_lower_mdi_clk_82543(hw, &ctrl);
	}

	e1000_raise_mdi_clk_82543(hw, &ctrl);
	e1000_lower_mdi_clk_82543(hw, &ctrl);

	return data;
}

/**
 *  e1000_phy_force_speed_duplex_82543 - Force speed/duplex for PHY
 *  @hw: pointer to the HW structure
 *
 *  Calls the function to force speed and duplex for the m88 PHY, and
 *  if the PHY is not auto-negotiating and the speed is forced to 10Mbit,
 *  then call the function for polarity reversal workaround.
 **/
STATIC s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw)
{
	s32 ret_val;

	DEBUGFUNC("e1000_phy_force_speed_duplex_82543");

	ret_val = e1000_phy_force_speed_duplex_m88(hw);
	if (ret_val)
		goto out;

	if (!hw->mac.autoneg && (hw->mac.forced_speed_duplex &
	    E1000_ALL_10_SPEED))
		ret_val = e1000_polarity_reversal_workaround_82543(hw);

out:
	return ret_val;
}

/**
 *  e1000_polarity_reversal_workaround_82543 - Workaround polarity reversal
 *  @hw: pointer to the HW structure
 *
 *  When forcing link to 10 Full or 10 Half, the PHY can reverse the polarity
 *  inadvertently.  To workaround the issue, we disable the transmitter on
 *  the PHY until we have established the link partner's link parameters.
 **/
STATIC s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw)
{
	s32 ret_val = E1000_SUCCESS;
	u16 mii_status_reg;
	u16 i;
	bool link;

	if (!(hw->phy.ops.write_reg))
		goto out;

	/* Polarity reversal workaround for forced 10F/10H links. */

	/* Disable the transmitter on the PHY */

	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
	if (ret_val)
		goto out;
	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
	if (ret_val)
		goto out;

	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
	if (ret_val)
		goto out;

	/*
	 * This loop will early-out if the NO link condition has been met.
	 * In other words, DO NOT use e1000_phy_has_link_generic() here.
	 */
	for (i = PHY_FORCE_TIME; i > 0; i--) {
		/*
		 * Read the MII Status Register and wait for Link Status bit
		 * to be clear.
		 */

		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
		if (ret_val)
			goto out;

		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
		if (ret_val)
			goto out;

		if (!(mii_status_reg & ~MII_SR_LINK_STATUS))
			break;
		msec_delay_irq(100);
	}

	/* Recommended delay time after link has been lost */
	msec_delay_irq(1000);

	/* Now we will re-enable the transmitter on the PHY */

	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
	if (ret_val)
		goto out;
	msec_delay_irq(50);
	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
	if (ret_val)
		goto out;
	msec_delay_irq(50);
	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
	if (ret_val)
		goto out;
	msec_delay_irq(50);
	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
	if (ret_val)
		goto out;

	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
	if (ret_val)
		goto out;

	/*
	 * Read the MII Status Register and wait for Link Status bit
	 * to be set.
	 */
	ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_TIME, 100000, &link);
	if (ret_val)
		goto out;

out:
	return ret_val;
}

/**
 *  e1000_phy_hw_reset_82543 - PHY hardware reset
 *  @hw: pointer to the HW structure
 *
 *  Sets the PHY_RESET_DIR bit in the extended device control register
 *  to put the PHY into a reset and waits for completion.  Once the reset
 *  has been accomplished, clear the PHY_RESET_DIR bit to take the PHY out
 *  of reset.
 **/
STATIC s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw)
{
	u32 ctrl_ext;
	s32 ret_val;

	DEBUGFUNC("e1000_phy_hw_reset_82543");

	/*
	 * Read the Extended Device Control Register, assert the PHY_RESET_DIR
	 * bit to put the PHY into reset...
	 */
	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
	ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
	ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
	E1000_WRITE_FLUSH(hw);

	msec_delay(10);

	/* ...then take it out of reset. */
	ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
	E1000_WRITE_FLUSH(hw);

	usec_delay(150);

	if (!(hw->phy.ops.get_cfg_done))
		return E1000_SUCCESS;

	ret_val = hw->phy.ops.get_cfg_done(hw);

	return ret_val;
}

/**
 *  e1000_reset_hw_82543 - Reset hardware
 *  @hw: pointer to the HW structure
 *
 *  This resets the hardware into a known state.
 **/
STATIC s32 e1000_reset_hw_82543(struct e1000_hw *hw)
{
	u32 ctrl;
	s32 ret_val = E1000_SUCCESS;

	DEBUGFUNC("e1000_reset_hw_82543");

	DEBUGOUT("Masking off all interrupts\n");
	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);

	E1000_WRITE_REG(hw, E1000_RCTL, 0);
	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
	E1000_WRITE_FLUSH(hw);

	e1000_set_tbi_sbp_82543(hw, false);

	/*
	 * Delay to allow any outstanding PCI transactions to complete before
	 * resetting the device
	 */
	msec_delay(10);

	ctrl = E1000_READ_REG(hw, E1000_CTRL);

	DEBUGOUT("Issuing a global reset to 82543/82544 MAC\n");
	if (hw->mac.type == e1000_82543) {
		E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
	} else {
		/*
		 * The 82544 can't ACK the 64-bit write when issuing the
		 * reset, so use IO-mapping as a workaround.
		 */
		E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
	}

	/*
	 * After MAC reset, force reload of NVM to restore power-on
	 * settings to device.
	 */
	hw->nvm.ops.reload(hw);
	msec_delay(2);

	/* Masking off and clearing any pending interrupts */
	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
	E1000_READ_REG(hw, E1000_ICR);

	return ret_val;
}

/**
 *  e1000_init_hw_82543 - Initialize hardware
 *  @hw: pointer to the HW structure
 *
 *  This inits the hardware readying it for operation.
 **/
STATIC s32 e1000_init_hw_82543(struct e1000_hw *hw)
{
	struct e1000_mac_info *mac = &hw->mac;
	struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
	u32 ctrl;
	s32 ret_val;
	u16 i;

	DEBUGFUNC("e1000_init_hw_82543");

	/* Disabling VLAN filtering */
	E1000_WRITE_REG(hw, E1000_VET, 0);
	mac->ops.clear_vfta(hw);

	/* Setup the receive address. */
	e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);

	/* Zero out the Multicast HASH table */
	DEBUGOUT("Zeroing the MTA\n");
	for (i = 0; i < mac->mta_reg_count; i++) {
		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
		E1000_WRITE_FLUSH(hw);
	}

	/*
	 * Set the PCI priority bit correctly in the CTRL register.  This
	 * determines if the adapter gives priority to receives, or if it
	 * gives equal priority to transmits and receives.
	 */
	if (hw->mac.type == e1000_82543 && dev_spec->dma_fairness) {
		ctrl = E1000_READ_REG(hw, E1000_CTRL);
		E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PRIOR);
	}

	e1000_pcix_mmrbc_workaround_generic(hw);

	/* Setup link and flow control */
	ret_val = mac->ops.setup_link(hw);

	/*
	 * Clear all of the statistics registers (clear on read).  It is
	 * important that we do this after we have tried to establish link
	 * because the symbol error count will increment wildly if there
	 * is no link.
	 */
	e1000_clear_hw_cntrs_82543(hw);

	return ret_val;
}

/**
 *  e1000_setup_link_82543 - Setup flow control and link settings
 *  @hw: pointer to the HW structure
 *
 *  Read the EEPROM to determine the initial polarity value and write the
 *  extended device control register with the information before calling
 *  the generic setup link function, which does the following:
 *  Determines which flow control settings to use, then configures flow
 *  control.  Calls the appropriate media-specific link configuration
 *  function.  Assuming the adapter has a valid link partner, a valid link
 *  should be established.  Assumes the hardware has previously been reset
 *  and the transmitter and receiver are not enabled.
 **/
STATIC s32 e1000_setup_link_82543(struct e1000_hw *hw)
{
	u32 ctrl_ext;
	s32  ret_val;
	u16 data;

	DEBUGFUNC("e1000_setup_link_82543");

	/*
	 * Take the 4 bits from NVM word 0xF that determine the initial
	 * polarity value for the SW controlled pins, and setup the
	 * Extended Device Control reg with that info.
	 * This is needed because one of the SW controlled pins is used for
	 * signal detection.  So this should be done before phy setup.
	 */
	if (hw->mac.type == e1000_82543) {
		ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data);
		if (ret_val) {
			DEBUGOUT("NVM Read Error\n");
			ret_val = -E1000_ERR_NVM;
			goto out;
		}
		ctrl_ext = ((data & NVM_WORD0F_SWPDIO_EXT_MASK) <<
			    NVM_SWDPIO_EXT_SHIFT);
		E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
	}

	ret_val = e1000_setup_link_generic(hw);

out:
	return ret_val;
}

/**
 *  e1000_setup_copper_link_82543 - Configure copper link settings
 *  @hw: pointer to the HW structure
 *
 *  Configures the link for auto-neg or forced speed and duplex.  Then we check
 *  for link, once link is established calls to configure collision distance
 *  and flow control are called.
 **/
STATIC s32 e1000_setup_copper_link_82543(struct e1000_hw *hw)
{
	u32 ctrl;
	s32 ret_val;
	bool link = true;

	DEBUGFUNC("e1000_setup_copper_link_82543");

	ctrl = E1000_READ_REG(hw, E1000_CTRL) | E1000_CTRL_SLU;
	/*
	 * With 82543, we need to force speed and duplex on the MAC
	 * equal to what the PHY speed and duplex configuration is.
	 * In addition, we need to perform a hardware reset on the
	 * PHY to take it out of reset.
	 */
	if (hw->mac.type == e1000_82543) {
		ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
		ret_val = hw->phy.ops.reset(hw);
		if (ret_val)
			goto out;
	} else {
		ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
	}

	/* Set MDI/MDI-X, Polarity Reversal, and downshift settings */
	ret_val = e1000_copper_link_setup_m88(hw);
	if (ret_val)
		goto out;

	if (hw->mac.autoneg) {
		/*
		 * Setup autoneg and flow control advertisement and perform
		 * autonegotiation.
		 */
		ret_val = e1000_copper_link_autoneg(hw);
		if (ret_val)
			goto out;
	} else {
		/*
		 * PHY will be set to 10H, 10F, 100H or 100F
		 * depending on user settings.
		 */
		DEBUGOUT("Forcing Speed and Duplex\n");
		ret_val = e1000_phy_force_speed_duplex_82543(hw);
		if (ret_val) {
			DEBUGOUT("Error Forcing Speed and Duplex\n");
			goto out;
		}
	}

	/*
	 * Check link status. Wait up to 100 microseconds for link to become
	 * valid.
	 */
	ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
					     &link);
	if (ret_val)
		goto out;


	if (link) {
		DEBUGOUT("Valid link established!!!\n");
		/* Config the MAC and PHY after link is up */
		if (hw->mac.type == e1000_82544) {
			hw->mac.ops.config_collision_dist(hw);
		} else {
			ret_val = e1000_config_mac_to_phy_82543(hw);
			if (ret_val)
				goto out;
		}
		ret_val = e1000_config_fc_after_link_up_generic(hw);
	} else {
		DEBUGOUT("Unable to establish link!!!\n");
	}

out:
	return ret_val;
}

/**
 *  e1000_setup_fiber_link_82543 - Setup link for fiber
 *  @hw: pointer to the HW structure
 *
 *  Configures collision distance and flow control for fiber links.  Upon
 *  successful setup, poll for link.
 **/
STATIC s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw)
{
	u32 ctrl;
	s32 ret_val;

	DEBUGFUNC("e1000_setup_fiber_link_82543");

	ctrl = E1000_READ_REG(hw, E1000_CTRL);

	/* Take the link out of reset */
	ctrl &= ~E1000_CTRL_LRST;

	hw->mac.ops.config_collision_dist(hw);

	ret_val = e1000_commit_fc_settings_generic(hw);
	if (ret_val)
		goto out;

	DEBUGOUT("Auto-negotiation enabled\n");

	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
	E1000_WRITE_FLUSH(hw);
	msec_delay(1);

	/*
	 * For these adapters, the SW definable pin 1 is cleared when the
	 * optics detect a signal.  If we have a signal, then poll for a
	 * "Link-Up" indication.
	 */
	if (!(E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1))
		ret_val = e1000_poll_fiber_serdes_link_generic(hw);
	else
		DEBUGOUT("No signal detected\n");

out:
	return ret_val;
}

/**
 *  e1000_check_for_copper_link_82543 - Check for link (Copper)
 *  @hw: pointer to the HW structure
 *
 *  Checks the phy for link, if link exists, do the following:
 *   - check for downshift
 *   - do polarity workaround (if necessary)
 *   - configure collision distance
 *   - configure flow control after link up
 *   - configure tbi compatibility
 **/
STATIC s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw)
{
	struct e1000_mac_info *mac = &hw->mac;
	u32 icr, rctl;
	s32 ret_val;
	u16 speed, duplex;
	bool link;

	DEBUGFUNC("e1000_check_for_copper_link_82543");

	if (!mac->get_link_status) {
		ret_val = E1000_SUCCESS;
		goto out;
	}

	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
	if (ret_val)
		goto out;

	if (!link)
		goto out; /* No link detected */

	mac->get_link_status = false;

	e1000_check_downshift_generic(hw);

	/*
	 * If we are forcing speed/duplex, then we can return since
	 * we have already determined whether we have link or not.
	 */
	if (!mac->autoneg) {
		/*
		 * If speed and duplex are forced to 10H or 10F, then we will
		 * implement the polarity reversal workaround.  We disable
		 * interrupts first, and upon returning, place the devices
		 * interrupt state to its previous value except for the link
		 * status change interrupt which will happened due to the
		 * execution of this workaround.
		 */
		if (mac->forced_speed_duplex & E1000_ALL_10_SPEED) {
			E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
			ret_val = e1000_polarity_reversal_workaround_82543(hw);
			icr = E1000_READ_REG(hw, E1000_ICR);
			E1000_WRITE_REG(hw, E1000_ICS, (icr & ~E1000_ICS_LSC));
			E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK);
		}

		ret_val = -E1000_ERR_CONFIG;
		goto out;
	}

	/*
	 * We have a M88E1000 PHY and Auto-Neg is enabled.  If we
	 * have Si on board that is 82544 or newer, Auto
	 * Speed Detection takes care of MAC speed/duplex
	 * configuration.  So we only need to configure Collision
	 * Distance in the MAC.  Otherwise, we need to force
	 * speed/duplex on the MAC to the current PHY speed/duplex
	 * settings.
	 */
	if (mac->type == e1000_82544)
		hw->mac.ops.config_collision_dist(hw);
	else {
		ret_val = e1000_config_mac_to_phy_82543(hw);
		if (ret_val) {
			DEBUGOUT("Error configuring MAC to PHY settings\n");
			goto out;
		}
	}

	/*
	 * Configure Flow Control now that Auto-Neg has completed.
	 * First, we need to restore the desired flow control
	 * settings because we may have had to re-autoneg with a
	 * different link partner.
	 */
	ret_val = e1000_config_fc_after_link_up_generic(hw);
	if (ret_val)
		DEBUGOUT("Error configuring flow control\n");

	/*
	 * At this point we know that we are on copper and we have
	 * auto-negotiated link.  These are conditions for checking the link
	 * partner capability register.  We use the link speed to determine if
	 * TBI compatibility needs to be turned on or off.  If the link is not
	 * at gigabit speed, then TBI compatibility is not needed.  If we are
	 * at gigabit speed, we turn on TBI compatibility.
	 */
	if (e1000_tbi_compatibility_enabled_82543(hw)) {
		ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
		if (ret_val) {
			DEBUGOUT("Error getting link speed and duplex\n");
			return ret_val;
		}
		if (speed != SPEED_1000) {
			/*
			 * If link speed is not set to gigabit speed,
			 * we do not need to enable TBI compatibility.
			 */
			if (e1000_tbi_sbp_enabled_82543(hw)) {
				/*
				 * If we previously were in the mode,
				 * turn it off.
				 */
				e1000_set_tbi_sbp_82543(hw, false);
				rctl = E1000_READ_REG(hw, E1000_RCTL);
				rctl &= ~E1000_RCTL_SBP;
				E1000_WRITE_REG(hw, E1000_RCTL, rctl);
			}
		} else {
			/*
			 * If TBI compatibility is was previously off,
			 * turn it on. For compatibility with a TBI link
			 * partner, we will store bad packets. Some
			 * frames have an additional byte on the end and
			 * will look like CRC errors to to the hardware.
			 */
			if (!e1000_tbi_sbp_enabled_82543(hw)) {
				e1000_set_tbi_sbp_82543(hw, true);
				rctl = E1000_READ_REG(hw, E1000_RCTL);
				rctl |= E1000_RCTL_SBP;
				E1000_WRITE_REG(hw, E1000_RCTL, rctl);
			}
		}
	}
out:
	return ret_val;
}

/**
 *  e1000_check_for_fiber_link_82543 - Check for link (Fiber)
 *  @hw: pointer to the HW structure
 *
 *  Checks for link up on the hardware.  If link is not up and we have
 *  a signal, then we need to force link up.
 **/
STATIC s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw)
{
	struct e1000_mac_info *mac = &hw->mac;
	u32 rxcw, ctrl, status;
	s32 ret_val = E1000_SUCCESS;

	DEBUGFUNC("e1000_check_for_fiber_link_82543");

	ctrl = E1000_READ_REG(hw, E1000_CTRL);
	status = E1000_READ_REG(hw, E1000_STATUS);
	rxcw = E1000_READ_REG(hw, E1000_RXCW);

	/*
	 * If we don't have link (auto-negotiation failed or link partner
	 * cannot auto-negotiate), the cable is plugged in (we have signal),
	 * and our link partner is not trying to auto-negotiate with us (we
	 * are receiving idles or data), we need to force link up. We also
	 * need to give auto-negotiation time to complete, in case the cable
	 * was just plugged in. The autoneg_failed flag does this.
	 */
	/* (ctrl & E1000_CTRL_SWDPIN1) == 0 == have signal */
	if ((!(ctrl & E1000_CTRL_SWDPIN1)) &&
	    (!(status & E1000_STATUS_LU)) &&
	    (!(rxcw & E1000_RXCW_C))) {
		if (!mac->autoneg_failed) {
			mac->autoneg_failed = true;
			ret_val = 0;
			goto out;
		}
		DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");

		/* Disable auto-negotiation in the TXCW register */
		E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));

		/* Force link-up and also force full-duplex. */
		ctrl = E1000_READ_REG(hw, E1000_CTRL);
		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);

		/* Configure Flow Control after forcing link up. */
		ret_val = e1000_config_fc_after_link_up_generic(hw);
		if (ret_val) {
			DEBUGOUT("Error configuring flow control\n");
			goto out;
		}
	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
		/*
		 * If we are forcing link and we are receiving /C/ ordered
		 * sets, re-enable auto-negotiation in the TXCW register
		 * and disable forced link in the Device Control register
		 * in an attempt to auto-negotiate with our link partner.
		 */
		DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
		E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
		E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));

		mac->serdes_has_link = true;
	}

out:
	return ret_val;
}

/**
 *  e1000_config_mac_to_phy_82543 - Configure MAC to PHY settings
 *  @hw: pointer to the HW structure
 *
 *  For the 82543 silicon, we need to set the MAC to match the settings
 *  of the PHY, even if the PHY is auto-negotiating.
 **/
STATIC s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw)
{
	u32 ctrl;
	s32 ret_val = E1000_SUCCESS;
	u16 phy_data;

	DEBUGFUNC("e1000_config_mac_to_phy_82543");

	if (!(hw->phy.ops.read_reg))
		goto out;

	/* Set the bits to force speed and duplex */
	ctrl = E1000_READ_REG(hw, E1000_CTRL);
	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
	ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);

	/*
	 * Set up duplex in the Device Control and Transmit Control
	 * registers depending on negotiated values.
	 */
	ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
	if (ret_val)
		goto out;

	ctrl &= ~E1000_CTRL_FD;
	if (phy_data & M88E1000_PSSR_DPLX)
		ctrl |= E1000_CTRL_FD;

	hw->mac.ops.config_collision_dist(hw);

	/*
	 * Set up speed in the Device Control register depending on
	 * negotiated values.
	 */
	if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
		ctrl |= E1000_CTRL_SPD_1000;
	else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
		ctrl |= E1000_CTRL_SPD_100;

	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);

out:
	return ret_val;
}

/**
 *  e1000_write_vfta_82543 - Write value to VLAN filter table
 *  @hw: pointer to the HW structure
 *  @offset: the 32-bit offset in which to write the value to.
 *  @value: the 32-bit value to write at location offset.
 *
 *  This writes a 32-bit value to a 32-bit offset in the VLAN filter
 *  table.
 **/
STATIC void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, u32 value)
{
	u32 temp;

	DEBUGFUNC("e1000_write_vfta_82543");

	if ((hw->mac.type == e1000_82544) && (offset & 1)) {
		temp = E1000_READ_REG_ARRAY(hw, E1000_VFTA, offset - 1);
		E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
		E1000_WRITE_FLUSH(hw);
		E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset - 1, temp);
		E1000_WRITE_FLUSH(hw);
	} else {
		e1000_write_vfta_generic(hw, offset, value);
	}
}

/**
 *  e1000_led_on_82543 - Turn on SW controllable LED
 *  @hw: pointer to the HW structure
 *
 *  Turns the SW defined LED on.
 **/
STATIC s32 e1000_led_on_82543(struct e1000_hw *hw)
{
	u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);

	DEBUGFUNC("e1000_led_on_82543");

	if (hw->mac.type == e1000_82544 &&
	    hw->phy.media_type == e1000_media_type_copper) {
		/* Clear SW-definable Pin 0 to turn on the LED */
		ctrl &= ~E1000_CTRL_SWDPIN0;
		ctrl |= E1000_CTRL_SWDPIO0;
	} else {
		/* Fiber 82544 and all 82543 use this method */
		ctrl |= E1000_CTRL_SWDPIN0;
		ctrl |= E1000_CTRL_SWDPIO0;
	}
	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);

	return E1000_SUCCESS;
}

/**
 *  e1000_led_off_82543 - Turn off SW controllable LED
 *  @hw: pointer to the HW structure
 *
 *  Turns the SW defined LED off.
 **/
STATIC s32 e1000_led_off_82543(struct e1000_hw *hw)
{
	u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);

	DEBUGFUNC("e1000_led_off_82543");

	if (hw->mac.type == e1000_82544 &&
	    hw->phy.media_type == e1000_media_type_copper) {
		/* Set SW-definable Pin 0 to turn off the LED */
		ctrl |= E1000_CTRL_SWDPIN0;
		ctrl |= E1000_CTRL_SWDPIO0;
	} else {
		ctrl &= ~E1000_CTRL_SWDPIN0;
		ctrl |= E1000_CTRL_SWDPIO0;
	}
	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);

	return E1000_SUCCESS;
}

/**
 *  e1000_clear_hw_cntrs_82543 - Clear device specific hardware counters
 *  @hw: pointer to the HW structure
 *
 *  Clears the hardware counters by reading the counter registers.
 **/
STATIC void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw)
{
	DEBUGFUNC("e1000_clear_hw_cntrs_82543");

	e1000_clear_hw_cntrs_base_generic(hw);

	E1000_READ_REG(hw, E1000_PRC64);
	E1000_READ_REG(hw, E1000_PRC127);
	E1000_READ_REG(hw, E1000_PRC255);
	E1000_READ_REG(hw, E1000_PRC511);
	E1000_READ_REG(hw, E1000_PRC1023);
	E1000_READ_REG(hw, E1000_PRC1522);
	E1000_READ_REG(hw, E1000_PTC64);
	E1000_READ_REG(hw, E1000_PTC127);
	E1000_READ_REG(hw, E1000_PTC255);
	E1000_READ_REG(hw, E1000_PTC511);
	E1000_READ_REG(hw, E1000_PTC1023);
	E1000_READ_REG(hw, E1000_PTC1522);

	E1000_READ_REG(hw, E1000_ALGNERRC);
	E1000_READ_REG(hw, E1000_RXERRC);
	E1000_READ_REG(hw, E1000_TNCRS);
	E1000_READ_REG(hw, E1000_CEXTERR);
	E1000_READ_REG(hw, E1000_TSCTC);
	E1000_READ_REG(hw, E1000_TSCTFC);
}
