++ ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);
++ if (ret_val == E1000_SUCCESS)
++ goto out;
++
++ for (program_retries = 0; program_retries < 100; program_retries++) {
++ e_dbg("Retrying Byte %2.2X at offset %u\n", byte, offset);
++ udelay(100);
++ ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);
++ if (ret_val == E1000_SUCCESS)
++ break;
++ }
++ if (program_retries == 100) {
++ ret_val = -E1000_ERR_NVM;
++ goto out;
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM
++ * @hw: pointer to the HW structure
++ * @bank: 0 for first bank, 1 for second bank, etc.
++ *
++ * Erases the bank specified. Each bank is a 4k block. Banks are 0 based.
++ * bank N is 4096 * N + flash_reg_addr.
++ **/
++static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
++{
++ struct e1000_nvm_info *nvm = &hw->nvm;
++ union ich8_hws_flash_status hsfsts;
++ union ich8_hws_flash_ctrl hsflctl;
++ u32 flash_linear_addr;
++ /* bank size is in 16bit words - adjust to bytes */
++ u32 flash_bank_size = nvm->flash_bank_size * 2;
++ s32 ret_val = E1000_SUCCESS;
++ s32 count = 0;
++ s32 j, iteration, sector_size;
++
++ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
++
++ /*
++ * Determine HW Sector size: Read BERASE bits of hw flash status
++ * register
++ * 00: The Hw sector is 256 bytes, hence we need to erase 16
++ * consecutive sectors. The start index for the nth Hw sector
++ * can be calculated as = bank * 4096 + n * 256
++ * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector.
++ * The start index for the nth Hw sector can be calculated
++ * as = bank * 4096
++ * 10: The Hw sector is 8K bytes, nth sector = bank * 8192
++ * (ich9 only, otherwise error condition)
++ * 11: The Hw sector is 64K bytes, nth sector = bank * 65536
++ */
++ switch (hsfsts.hsf_status.berasesz) {
++ case 0:
++ /* Hw sector size 256 */
++ sector_size = ICH_FLASH_SEG_SIZE_256;
++ iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256;
++ break;
++ case 1:
++ sector_size = ICH_FLASH_SEG_SIZE_4K;
++ iteration = 1;
++ break;
++ case 2:
++ if (hw->mac.type == e1000_ich9lan) {
++ sector_size = ICH_FLASH_SEG_SIZE_8K;
++ iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_8K;
++ } else {
++ ret_val = -E1000_ERR_NVM;
++ goto out;
++ }
++ break;
++ case 3:
++ sector_size = ICH_FLASH_SEG_SIZE_64K;
++ iteration = 1;
++ break;
++ default:
++ ret_val = -E1000_ERR_NVM;
++ goto out;
++ }
++
++ /* Start with the base address, then add the sector offset. */
++ flash_linear_addr = hw->nvm.flash_base_addr;
++ flash_linear_addr += (bank) ? (sector_size * iteration) : 0;
++
++ for (j = 0; j < iteration ; j++) {
++ do {
++ /* Steps */
++ ret_val = e1000_flash_cycle_init_ich8lan(hw);
++ if (ret_val)
++ goto out;
++
++ /*
++ * Write a value 11 (block Erase) in Flash
++ * Cycle field in hw flash control
++ */
++ hsflctl.regval = er16flash(
++ ICH_FLASH_HSFCTL);
++ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
++ ew16flash(ICH_FLASH_HSFCTL,
++ hsflctl.regval);
++
++ /*
++ * Write the last 24 bits of an index within the
++ * block into Flash Linear address field in Flash
++ * Address.
++ */
++ flash_linear_addr += (j * sector_size);
++ ew32flash(ICH_FLASH_FADDR,
++ flash_linear_addr);
++
++ ret_val = e1000_flash_cycle_ich8lan(hw,
++ ICH_FLASH_ERASE_COMMAND_TIMEOUT);
++ if (ret_val == E1000_SUCCESS)
++ break;
++
++ /*
++ * Check if FCERR is set to 1. If 1,
++ * clear it and try the whole sequence
++ * a few more times else Done
++ */
++ hsfsts.regval = er16flash(
++ ICH_FLASH_HSFSTS);
++ if (hsfsts.hsf_status.flcerr == 1)
++ /* repeat for some time before giving up */
++ continue;
++ else if (hsfsts.hsf_status.flcdone == 0)
++ goto out;
++ } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT);
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_valid_led_default_ich8lan - Set the default LED settings
++ * @hw: pointer to the HW structure
++ * @data: Pointer to the LED settings
++ *
++ * Reads the LED default settings from the NVM to data. If the NVM LED
++ * settings is all 0's or F's, set the LED default to a valid LED default
++ * setting.
++ **/
++static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data)
++{
++ s32 ret_val;
++
++ ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data);
++ if (ret_val) {
++ e_dbg("NVM Read Error\n");
++ goto out;
++ }
++
++ if (*data == ID_LED_RESERVED_0000 ||
++ *data == ID_LED_RESERVED_FFFF)
++ *data = ID_LED_DEFAULT_ICH8LAN;
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_id_led_init_pchlan - store LED configurations
++ * @hw: pointer to the HW structure
++ *
++ * PCH does not control LEDs via the LEDCTL register, rather it uses
++ * the PHY LED configuration register.
++ *
++ * PCH also does not have an "always on" or "always off" mode which
++ * complicates the ID feature. Instead of using the "on" mode to indicate
++ * in ledctl_mode2 the LEDs to use for ID (see e1000e_id_led_init()),
++ * use "link_up" mode. The LEDs will still ID on request if there is no
++ * link based on logic in e1000_led_[on|off]_pchlan().
++ **/
++static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++ s32 ret_val;
++ const u32 ledctl_on = E1000_LEDCTL_MODE_LINK_UP;
++ const u32 ledctl_off = E1000_LEDCTL_MODE_LINK_UP | E1000_PHY_LED0_IVRT;
++ u16 data, i, temp, shift;
++
++ /* Get default ID LED modes */
++ ret_val = hw->nvm.ops.valid_led_default(hw, &data);
++ if (ret_val)
++ goto out;
++
++ mac->ledctl_default = er32(LEDCTL);
++ mac->ledctl_mode1 = mac->ledctl_default;
++ mac->ledctl_mode2 = mac->ledctl_default;
++
++ for (i = 0; i < 4; i++) {
++ temp = (data >> (i << 2)) & E1000_LEDCTL_LED0_MODE_MASK;
++ shift = (i * 5);
++ switch (temp) {
++ case ID_LED_ON1_DEF2:
++ case ID_LED_ON1_ON2:
++ case ID_LED_ON1_OFF2:
++ mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift);
++ mac->ledctl_mode1 |= (ledctl_on << shift);
++ break;
++ case ID_LED_OFF1_DEF2:
++ case ID_LED_OFF1_ON2:
++ case ID_LED_OFF1_OFF2:
++ mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift);
++ mac->ledctl_mode1 |= (ledctl_off << shift);
++ break;
++ default:
++ /* Do nothing */
++ break;
++ }
++ switch (temp) {
++ case ID_LED_DEF1_ON2:
++ case ID_LED_ON1_ON2:
++ case ID_LED_OFF1_ON2:
++ mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift);
++ mac->ledctl_mode2 |= (ledctl_on << shift);
++ break;
++ case ID_LED_DEF1_OFF2:
++ case ID_LED_ON1_OFF2:
++ case ID_LED_OFF1_OFF2:
++ mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift);
++ mac->ledctl_mode2 |= (ledctl_off << shift);
++ break;
++ default:
++ /* Do nothing */
++ break;
++ }
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_get_bus_info_ich8lan - Get/Set the bus type and width
++ * @hw: pointer to the HW structure
++ *
++ * ICH8 use the PCI Express bus, but does not contain a PCI Express Capability
++ * register, so the the bus width is hard coded.
++ **/
++static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
++{
++ struct e1000_bus_info *bus = &hw->bus;
++ s32 ret_val;
++
++ ret_val = e1000e_get_bus_info_pcie(hw);
++
++ /*
++ * ICH devices are "PCI Express"-ish. They have
++ * a configuration space, but do not contain
++ * PCI Express Capability registers, so bus width
++ * must be hardcoded.
++ */
++ if (bus->width == e1000_bus_width_unknown)
++ bus->width = e1000_bus_width_pcie_x1;
++
++ return ret_val;
++}
++
++/**
++ * e1000_reset_hw_ich8lan - Reset the hardware
++ * @hw: pointer to the HW structure
++ *
++ * Does a full reset of the hardware which includes a reset of the PHY and
++ * MAC.
++ **/
++static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
++{
++ u32 ctrl, icr, kab;
++ s32 ret_val;
++
++ /*
++ * Prevent the PCI-E bus from sticking if there is no TLP connection
++ * on the last TLP read/write transaction when MAC is reset.
++ */
++ ret_val = e1000e_disable_pcie_master(hw);
++ if (ret_val)
++ e_dbg("PCI-E Master disable polling has failed.\n");
++
++ e_dbg("Masking off all interrupts\n");
++ ew32(IMC, 0xffffffff);
++
++ /*
++ * Disable the Transmit and Receive units. Then delay to allow
++ * any pending transactions to complete before we hit the MAC
++ * with the global reset.
++ */
++ ew32(RCTL, 0);
++ ew32(TCTL, E1000_TCTL_PSP);
++ e1e_flush();
++
++ msleep(10);
++
++ /* Workaround for ICH8 bit corruption issue in FIFO memory */
++ if (hw->mac.type == e1000_ich8lan) {
++ /* Set Tx and Rx buffer allocation to 8k apiece. */
++ ew32(PBA, E1000_PBA_8K);
++ /* Set Packet Buffer Size to 16k. */
++ ew32(PBS, E1000_PBS_16K);
++ }
++
++ ctrl = er32(CTRL);
++
++ if (!e1000_check_reset_block(hw) && !hw->phy.reset_disable) {
++ /* Clear PHY Reset Asserted bit */
++ if (hw->mac.type >= e1000_pchlan) {
++ u32 status = er32(STATUS);
++ ew32(STATUS, status &
++ ~E1000_STATUS_PHYRA);
++ }
++
++ /*
++ * PHY HW reset requires MAC CORE reset at the same
++ * time to make sure the interface between MAC and the
++ * external PHY is reset.
++ */
++ ctrl |= E1000_CTRL_PHY_RST;
++ }
++ ret_val = e1000_acquire_swflag_ich8lan(hw);
++ e_dbg("Issuing a global reset to ich8lan\n");
++ ew32(CTRL, (ctrl | E1000_CTRL_RST));
++ msleep(20);
++
++ if (!ret_val)
++ e1000_release_swflag_ich8lan(hw);
++
++ if (ctrl & E1000_CTRL_PHY_RST)
++ ret_val = hw->phy.ops.get_cfg_done(hw);
++
++ if (hw->mac.type >= e1000_ich10lan) {
++ e1000_lan_init_done_ich8lan(hw);
++ } else {
++ if (!ret_val) {
++ /* release the swflag because it is not reset by
++ * hardware reset
++ */
++ e1000_release_swflag_ich8lan(hw);
++ }
++
++ ret_val = e1000e_get_auto_rd_done(hw);
++ if (ret_val) {
++ /*
++ * When auto config read does not complete, do not
++ * return with an error. This can happen in situations
++ * where there is no eeprom and prevents getting link.
++ */
++ e_dbg("Auto Read Done did not complete\n");
++ }
++ }
++
++ /*
++ * For PCH, this write will make sure that any noise
++ * will be detected as a CRC error and be dropped rather than show up
++ * as a bad packet to the DMA engine.
++ */
++ if (hw->mac.type == e1000_pchlan)
++ ew32(CRC_OFFSET, 0x65656565);
++
++ ew32(IMC, 0xffffffff);
++ icr = er32(ICR);
++
++ kab = er32(KABGTXD);
++ kab |= E1000_KABGTXD_BGSQLBIAS;
++ ew32(KABGTXD, kab);
++
++ if (hw->mac.type == e1000_pchlan)
++ ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
++
++ return ret_val;
++}
++
++/**
++ * e1000_init_hw_ich8lan - Initialize the hardware
++ * @hw: pointer to the HW structure
++ *
++ * Prepares the hardware for transmit and receive by doing the following:
++ * - initialize hardware bits
++ * - initialize LED identification
++ * - setup receive address registers
++ * - setup flow control
++ * - setup transmit descriptors
++ * - clear statistics
++ **/
++static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++ u32 ctrl_ext, txdctl, snoop;
++ s32 ret_val;
++ u16 i;
++
++ e1000_initialize_hw_bits_ich8lan(hw);
++
++ /* Initialize identification LED */
++ ret_val = mac->ops.id_led_init(hw);
++ if (ret_val)
++ /* This is not fatal and we should not stop init due to this */
++ e_dbg("Error initializing identification LED\n");
++
++ /* Setup the receive address. */
++ e1000e_init_rx_addrs(hw, mac->rar_entry_count);
++
++ /* Zero out the Multicast HASH table */
++ e_dbg("Zeroing the MTA\n");
++ for (i = 0; i < mac->mta_reg_count; i++)
++ E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
++
++ /*
++ * The 82578 Rx buffer will stall if wakeup is enabled in host and
++ * the ME. Reading the BM_WUC register will clear the host wakeup bit.
++ * Reset the phy after disabling host wakeup to reset the Rx buffer.
++ */
++ if (hw->phy.type == e1000_phy_82578) {
++ e1e_rphy(hw, BM_WUC, &i);
++ ret_val = e1000_phy_hw_reset_ich8lan(hw);
++ if (ret_val)
++ return ret_val;
++ }
++
++ /* Setup link and flow control */
++ ret_val = mac->ops.setup_link(hw);
++
++ /* Set the transmit descriptor write-back policy for both queues */
++ txdctl = er32(TXDCTL(0));
++ txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
++ E1000_TXDCTL_FULL_TX_DESC_WB;
++ txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
++ E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
++ ew32(TXDCTL(0), txdctl);
++ txdctl = er32(TXDCTL(1));
++ txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
++ E1000_TXDCTL_FULL_TX_DESC_WB;
++ txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
++ E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
++ ew32(TXDCTL(1), txdctl);
++
++ /*
++ * ICH8 has opposite polarity of no_snoop bits.
++ * By default, we should use snoop behavior.
++ */
++ if (mac->type == e1000_ich8lan)
++ snoop = PCIE_ICH8_SNOOP_ALL;
++ else
++ snoop = (u32)~(PCIE_NO_SNOOP_ALL);
++ e1000e_set_pcie_no_snoop(hw, snoop);
++
++ ctrl_ext = er32(CTRL_EXT);
++ ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
++ ew32(CTRL_EXT, ctrl_ext);
++
++ /*
++ * 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_ich8lan(hw);
++
++ return ret_val;
++}
++/**
++ * e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits
++ * @hw: pointer to the HW structure
++ *
++ * Sets/Clears required hardware bits necessary for correctly setting up the
++ * hardware for transmit and receive.
++ **/
++static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
++{
++ u32 reg;
++
++ /* Extended Device Control */
++ reg = er32(CTRL_EXT);
++ reg |= (1 << 22);
++ /* Enable PHY low-power state when MAC is at D3 w/o WoL */
++ if (hw->mac.type >= e1000_pchlan)
++ reg |= E1000_CTRL_EXT_PHYPDEN;
++ ew32(CTRL_EXT, reg);
++
++ /* Transmit Descriptor Control 0 */
++ reg = er32(TXDCTL(0));
++ reg |= (1 << 22);
++ ew32(TXDCTL(0), reg);
++
++ /* Transmit Descriptor Control 1 */
++ reg = er32(TXDCTL(1));
++ reg |= (1 << 22);
++ ew32(TXDCTL(1), reg);
++
++ /* Transmit Arbitration Control 0 */
++ reg = er32(TARC(0));
++ if (hw->mac.type == e1000_ich8lan)
++ reg |= (1 << 28) | (1 << 29);
++ reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27);
++ ew32(TARC(0), reg);
++
++ /* Transmit Arbitration Control 1 */
++ reg = er32(TARC(1));
++ if (er32(TCTL) & E1000_TCTL_MULR)
++ reg &= ~(1 << 28);
++ else
++ reg |= (1 << 28);
++ reg |= (1 << 24) | (1 << 26) | (1 << 30);
++ ew32(TARC(1), reg);
++
++ /* Device Status */
++ if (hw->mac.type == e1000_ich8lan) {
++ reg = er32(STATUS);
++ reg &= ~(1 << 31);
++ ew32(STATUS, reg);
++ }
++
++ return;
++}
++
++/**
++ * e1000_setup_link_ich8lan - Setup flow control and link settings
++ * @hw: pointer to the HW structure
++ *
++ * 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_ich8lan(struct e1000_hw *hw)
++{
++ s32 ret_val = E1000_SUCCESS;
++
++ if (e1000_check_reset_block(hw))
++ goto out;
++
++ /*
++ * ICH parts do not have a word in the NVM to determine
++ * the default flow control setting, so we explicitly
++ * set it to full.
++ */
++ if (hw->fc.requested_mode == e1000_fc_default)
++ hw->fc.requested_mode = e1000_fc_full;
++
++ /*
++ * Save off the requested flow control mode for use later. Depending
++ * on the link partner's capabilities, we may or may not use this mode.
++ */
++ hw->fc.current_mode = hw->fc.requested_mode;
++
++ e_dbg("After fix-ups FlowControl is now = %x\n",
++ hw->fc.current_mode);
++
++ /* Continue to configure the copper link. */
++ ret_val = hw->mac.ops.setup_physical_interface(hw);
++ if (ret_val)
++ goto out;
++
++ ew32(FCTTV, hw->fc.pause_time);
++ if ((hw->phy.type == e1000_phy_82578) ||
++ (hw->phy.type == e1000_phy_82577)) {
++ ret_val = e1e_wphy(hw,
++ PHY_REG(BM_PORT_CTRL_PAGE, 27),
++ hw->fc.pause_time);
++ if (ret_val)
++ goto out;
++ }
++
++ ret_val = e1000e_set_fc_watermarks(hw);
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_setup_copper_link_ich8lan - Configure MAC/PHY interface
++ * @hw: pointer to the HW structure
++ *
++ * Configures the kumeran interface to the PHY to wait the appropriate time
++ * when polling the PHY, then call the generic setup_copper_link to finish
++ * configuring the copper link.
++ **/
++static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
++{
++ u32 ctrl;
++ s32 ret_val;
++ u16 reg_data;
++
++ ctrl = er32(CTRL);
++ ctrl |= E1000_CTRL_SLU;
++ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
++ ew32(CTRL, ctrl);
++
++ /*
++ * Set the mac to wait the maximum time between each iteration
++ * and increase the max iterations when polling the phy;
++ * this fixes erroneous timeouts at 10Mbps.
++ */
++ ret_val = e1000e_write_kmrn_reg(hw,
++ E1000_KMRNCTRLSTA_TIMEOUTS,
++ 0xFFFF);
++ if (ret_val)
++ goto out;
++ ret_val = e1000e_read_kmrn_reg(hw,
++ E1000_KMRNCTRLSTA_INBAND_PARAM,
++ ®_data);
++ if (ret_val)
++ goto out;
++ reg_data |= 0x3F;
++ ret_val = e1000e_write_kmrn_reg(hw,
++ E1000_KMRNCTRLSTA_INBAND_PARAM,
++ reg_data);
++ if (ret_val)
++ goto out;
++
++ switch (hw->phy.type) {
++ case e1000_phy_igp_3:
++ ret_val = e1000e_copper_link_setup_igp(hw);
++ if (ret_val)
++ goto out;
++ break;
++ case e1000_phy_bm:
++ case e1000_phy_82578:
++ ret_val = e1000e_copper_link_setup_m88(hw);
++ if (ret_val)
++ goto out;
++ break;
++ case e1000_phy_82577:
++ ret_val = e1000_copper_link_setup_82577(hw);
++ if (ret_val)
++ goto out;
++ break;
++ case e1000_phy_ife:
++ ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL,
++ ®_data);
++ if (ret_val)
++ goto out;
++
++ reg_data &= ~IFE_PMC_AUTO_MDIX;
++
++ switch (hw->phy.mdix) {
++ case 1:
++ reg_data &= ~IFE_PMC_FORCE_MDIX;
++ break;
++ case 2:
++ reg_data |= IFE_PMC_FORCE_MDIX;
++ break;
++ case 0:
++ default:
++ reg_data |= IFE_PMC_AUTO_MDIX;
++ break;
++ }
++ ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL,
++ reg_data);
++ if (ret_val)
++ goto out;
++ break;
++ default:
++ break;
++ }
++ ret_val = e1000e_setup_copper_link(hw);
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_get_link_up_info_ich8lan - Get current link speed and duplex
++ * @hw: pointer to the HW structure
++ * @speed: pointer to store current link speed
++ * @duplex: pointer to store the current link duplex
++ *
++ * Calls the generic get_speed_and_duplex to retrieve the current link
++ * information and then calls the Kumeran lock loss workaround for links at
++ * gigabit speeds.
++ **/
++static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
++ u16 *duplex)
++{
++ s32 ret_val;
++
++ ret_val = e1000e_get_speed_and_duplex_copper(hw, speed, duplex);
++ if (ret_val)
++ goto out;
++
++ if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) {
++ ret_val = e1000e_write_kmrn_reg(hw,
++ E1000_KMRNCTRLSTA_K1_CONFIG,
++ E1000_KMRNCTRLSTA_K1_DISABLE);
++ if (ret_val)
++ goto out;
++ }
++
++ if ((hw->mac.type == e1000_ich8lan) &&
++ (hw->phy.type == e1000_phy_igp_3) &&
++ (*speed == SPEED_1000)) {
++ ret_val = e1000_kmrn_lock_loss_workaround_ich8lan(hw);
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_kmrn_lock_loss_workaround_ich8lan - Kumeran workaround
++ * @hw: pointer to the HW structure
++ *
++ * Work-around for 82566 Kumeran PCS lock loss:
++ * On link status change (i.e. PCI reset, speed change) and link is up and
++ * speed is gigabit-
++ * 0) if workaround is optionally disabled do nothing
++ * 1) wait 1ms for Kumeran link to come up
++ * 2) check Kumeran Diagnostic register PCS lock loss bit
++ * 3) if not set the link is locked (all is good), otherwise...
++ * 4) reset the PHY
++ * 5) repeat up to 10 times
++ * Note: this is only called for IGP3 copper when speed is 1gb.
++ **/
++static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
++{
++ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
++ u32 phy_ctrl;
++ s32 ret_val = E1000_SUCCESS;
++ u16 i, data;
++ bool link;
++
++ if (!(dev_spec->kmrn_lock_loss_workaround_enabled))
++ goto out;
++
++ /*
++ * Make sure link is up before proceeding. If not just return.
++ * Attempting this while link is negotiating fouled up link
++ * stability
++ */
++ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
++ if (!link) {
++ ret_val = E1000_SUCCESS;
++ goto out;
++ }
++
++ for (i = 0; i < 10; i++) {
++ /* read once to clear */
++ ret_val = e1e_rphy(hw, IGP3_KMRN_DIAG, &data);
++ if (ret_val)
++ goto out;
++ /* and again to get new status */
++ ret_val = e1e_rphy(hw, IGP3_KMRN_DIAG, &data);
++ if (ret_val)
++ goto out;
++
++ /* check for PCS lock */
++ if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS)) {
++ ret_val = E1000_SUCCESS;
++ goto out;
++ }
++
++ /* Issue PHY reset */
++ e1000_phy_hw_reset(hw);
++ mdelay(5);
++ }
++ /* Disable GigE link negotiation */
++ phy_ctrl = er32(PHY_CTRL);
++ phy_ctrl |= (E1000_PHY_CTRL_GBE_DISABLE |
++ E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
++ ew32(PHY_CTRL, phy_ctrl);
++
++ /*
++ * Call gig speed drop workaround on Gig disable before accessing
++ * any PHY registers
++ */
++ e1000e_gig_downshift_workaround_ich8lan(hw);
++
++ /* unable to acquire PCS lock */
++ ret_val = -E1000_ERR_PHY;
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state
++ * @hw: pointer to the HW structure
++ * @state: boolean value used to set the current Kumeran workaround state
++ *
++ * If ICH8, set the current Kumeran workaround state (enabled - true
++ * /disabled - false).
++ **/
++void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
++ bool state)
++{
++ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
++
++ if (hw->mac.type != e1000_ich8lan) {
++ e_dbg("Workaround applies to ICH8 only.\n");
++ return;
++ }
++
++ dev_spec->kmrn_lock_loss_workaround_enabled = state;
++
++ return;
++}
++
++/**
++ * e1000_ipg3_phy_powerdown_workaround_ich8lan - Power down workaround on D3
++ * @hw: pointer to the HW structure
++ *
++ * Workaround for 82566 power-down on D3 entry:
++ * 1) disable gigabit link
++ * 2) write VR power-down enable
++ * 3) read it back
++ * Continue if successful, else issue LCD reset and repeat
++ **/
++void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
++{
++ u32 reg;
++ u16 data;
++ u8 retry = 0;
++
++ if (hw->phy.type != e1000_phy_igp_3)
++ goto out;
++
++ /* Try the workaround twice (if needed) */
++ do {
++ /* Disable link */
++ reg = er32(PHY_CTRL);
++ reg |= (E1000_PHY_CTRL_GBE_DISABLE |
++ E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
++ ew32(PHY_CTRL, reg);
++
++ /*
++ * Call gig speed drop workaround on Gig disable before
++ * accessing any PHY registers
++ */
++ if (hw->mac.type == e1000_ich8lan)
++ e1000e_gig_downshift_workaround_ich8lan(hw);
++
++ /* Write VR power-down enable */
++ e1e_rphy(hw, IGP3_VR_CTRL, &data);
++ data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK;
++ e1e_wphy(hw, IGP3_VR_CTRL,
++ data | IGP3_VR_CTRL_MODE_SHUTDOWN);
++
++ /* Read it back and test */
++ e1e_rphy(hw, IGP3_VR_CTRL, &data);
++ data &= IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK;
++ if ((data == IGP3_VR_CTRL_MODE_SHUTDOWN) || retry)
++ break;
++
++ /* Issue PHY reset and repeat at most one more time */
++ reg = er32(CTRL);
++ ew32(CTRL, reg | E1000_CTRL_PHY_RST);
++ retry++;
++ } while (retry);
++
++out:
++ return;
++}
++
++/**
++ * e1000e_gig_downshift_workaround_ich8lan - WoL from S5 stops working
++ * @hw: pointer to the HW structure
++ *
++ * Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC),
++ * LPLU, Gig disable, MDIC PHY reset):
++ * 1) Set Kumeran Near-end loopback
++ * 2) Clear Kumeran Near-end loopback
++ * Should only be called for ICH8[m] devices with IGP_3 Phy.
++ **/
++void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
++{
++ s32 ret_val = E1000_SUCCESS;
++ u16 reg_data;
++
++ if ((hw->mac.type != e1000_ich8lan) ||
++ (hw->phy.type != e1000_phy_igp_3))
++ goto out;
++
++ ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
++ ®_data);
++ if (ret_val)
++ goto out;
++ reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK;
++ ret_val = e1000e_write_kmrn_reg(hw,
++ E1000_KMRNCTRLSTA_DIAG_OFFSET,
++ reg_data);
++ if (ret_val)
++ goto out;
++ reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK;
++ ret_val = e1000e_write_kmrn_reg(hw,
++ E1000_KMRNCTRLSTA_DIAG_OFFSET,
++ reg_data);
++out:
++ return;
++}
++
++/**
++ * e1000e_disable_gig_wol_ich8lan - disable gig during WoL
++ * @hw: pointer to the HW structure
++ *
++ * During S0 to Sx transition, it is possible the link remains at gig
++ * instead of negotiating to a lower speed. Before going to Sx, set
++ * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
++ * to a lower speed.
++ *
++ * Should only be called for applicable parts.
++ **/
++void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
++{
++ u32 phy_ctrl;
++
++ switch (hw->mac.type) {
++ case e1000_ich9lan:
++ case e1000_ich10lan:
++ case e1000_pchlan:
++ phy_ctrl = er32(PHY_CTRL);
++ phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU |
++ E1000_PHY_CTRL_GBE_DISABLE;
++ ew32(PHY_CTRL, phy_ctrl);
++
++ /* Workaround SWFLAG unexpectedly set during S0->Sx */
++ if (hw->mac.type == e1000_pchlan)
++ udelay(500);
++ default:
++ break;
++ }
++
++ return;
++}
++
++/**
++ * e1000_cleanup_led_ich8lan - Restore the default LED operation
++ * @hw: pointer to the HW structure
++ *
++ * Return the LED back to the default configuration.
++ **/
++static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw)
++{
++ s32 ret_val = E1000_SUCCESS;
++
++ if (hw->phy.type == e1000_phy_ife)
++ ret_val = e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED,
++ 0);
++ else
++ ew32(LEDCTL, hw->mac.ledctl_default);
++
++ return ret_val;
++}
++
++/**
++ * e1000_led_on_ich8lan - Turn LEDs on
++ * @hw: pointer to the HW structure
++ *
++ * Turn on the LEDs.
++ **/
++static s32 e1000_led_on_ich8lan(struct e1000_hw *hw)
++{
++ s32 ret_val = E1000_SUCCESS;
++
++ if (hw->phy.type == e1000_phy_ife)
++ ret_val = e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED,
++ (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON));
++ else
++ ew32(LEDCTL, hw->mac.ledctl_mode2);
++
++ return ret_val;
++}
++
++/**
++ * e1000_led_off_ich8lan - Turn LEDs off
++ * @hw: pointer to the HW structure
++ *
++ * Turn off the LEDs.
++ **/
++static s32 e1000_led_off_ich8lan(struct e1000_hw *hw)
++{
++ s32 ret_val = E1000_SUCCESS;
++
++ if (hw->phy.type == e1000_phy_ife)
++ ret_val = e1e_wphy(hw,
++ IFE_PHY_SPECIAL_CONTROL_LED,
++ (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF));
++ else
++ ew32(LEDCTL, hw->mac.ledctl_mode1);
++
++ return ret_val;
++}
++
++/**
++ * e1000_setup_led_pchlan - Configures SW controllable LED
++ * @hw: pointer to the HW structure
++ *
++ * This prepares the SW controllable LED for use.
++ **/
++static s32 e1000_setup_led_pchlan(struct e1000_hw *hw)
++{
++ return e1e_wphy(hw, HV_LED_CONFIG,
++ (u16)hw->mac.ledctl_mode1);
++}
++
++/**
++ * e1000_cleanup_led_pchlan - Restore the default LED operation
++ * @hw: pointer to the HW structure
++ *
++ * Return the LED back to the default configuration.
++ **/
++static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw)
++{
++ return e1e_wphy(hw, HV_LED_CONFIG,
++ (u16)hw->mac.ledctl_default);
++}
++
++/**
++ * e1000_led_on_pchlan - Turn LEDs on
++ * @hw: pointer to the HW structure
++ *
++ * Turn on the LEDs.
++ **/
++static s32 e1000_led_on_pchlan(struct e1000_hw *hw)
++{
++ u16 data = (u16)hw->mac.ledctl_mode2;
++ u32 i, led;
++
++ /*
++ * If no link, then turn LED on by setting the invert bit
++ * for each LED that's mode is "link_up" in ledctl_mode2.
++ */
++ if (!(er32(STATUS) & E1000_STATUS_LU)) {
++ for (i = 0; i < 3; i++) {
++ led = (data >> (i * 5)) & E1000_PHY_LED0_MASK;
++ if ((led & E1000_PHY_LED0_MODE_MASK) !=
++ E1000_LEDCTL_MODE_LINK_UP)
++ continue;
++ if (led & E1000_PHY_LED0_IVRT)
++ data &= ~(E1000_PHY_LED0_IVRT << (i * 5));
++ else
++ data |= (E1000_PHY_LED0_IVRT << (i * 5));
++ }
++ }
++
++ return e1e_wphy(hw, HV_LED_CONFIG, data);
++}
++
++/**
++ * e1000_led_off_pchlan - Turn LEDs off
++ * @hw: pointer to the HW structure
++ *
++ * Turn off the LEDs.
++ **/
++static s32 e1000_led_off_pchlan(struct e1000_hw *hw)
++{
++ u16 data = (u16)hw->mac.ledctl_mode1;
++ u32 i, led;
++
++ /*
++ * If no link, then turn LED off by clearing the invert bit
++ * for each LED that's mode is "link_up" in ledctl_mode1.
++ */
++ if (!(er32(STATUS) & E1000_STATUS_LU)) {
++ for (i = 0; i < 3; i++) {
++ led = (data >> (i * 5)) & E1000_PHY_LED0_MASK;
++ if ((led & E1000_PHY_LED0_MODE_MASK) !=
++ E1000_LEDCTL_MODE_LINK_UP)
++ continue;
++ if (led & E1000_PHY_LED0_IVRT)
++ data &= ~(E1000_PHY_LED0_IVRT << (i * 5));
++ else
++ data |= (E1000_PHY_LED0_IVRT << (i * 5));
++ }
++ }
++
++ return e1e_wphy(hw, HV_LED_CONFIG, data);
++}
++
++/**
++ * e1000_get_cfg_done_ich8lan - Read config done bit
++ * @hw: pointer to the HW structure
++ *
++ * Read the management control register for the config done bit for
++ * completion status. NOTE: silicon which is EEPROM-less will fail trying
++ * to read the config done bit, so an error is *ONLY* logged and returns
++ * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon
++ * would not be able to be reset or change link.
++ **/
++static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
++{
++ s32 ret_val = E1000_SUCCESS;
++ u32 bank = 0;
++
++ if (hw->mac.type >= e1000_pchlan) {
++ u32 status = er32(STATUS);
++
++ if (status & E1000_STATUS_PHYRA) {
++ ew32(STATUS, status &
++ ~E1000_STATUS_PHYRA);
++ } else
++ e_dbg("PHY Reset Asserted not set - needs delay\n");
++ }
++
++ e1000e_get_cfg_done(hw);
++
++ /* If EEPROM is not marked present, init the IGP 3 PHY manually */
++ if ((hw->mac.type != e1000_ich10lan) &&
++ (hw->mac.type != e1000_pchlan)) {
++ if (((er32(EECD) & E1000_EECD_PRES) == 0) &&
++ (hw->phy.type == e1000_phy_igp_3)) {
++ e1000_phy_init_script_igp3(hw);
++ }
++ } else {
++ if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) {
++ /* Maybe we should do a basic PHY config */
++ e_dbg("EEPROM not present\n");
++ ret_val = -E1000_ERR_CONFIG;
++ }
++ }
++
++ return ret_val;
++}
++
++/**
++ * e1000_power_down_phy_copper_ich8lan - Remove link during PHY power down
++ * @hw: pointer to the HW structure
++ *
++ * In the case of a PHY power down to save power, or to turn off link during a
++ * driver unload, or wake on lan is not enabled, remove the link.
++ **/
++static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw)
++{
++ /* If the management interface is not enabled, then power down */
++ if (!(hw->mac.ops.check_mng_mode(hw) ||
++ e1000_check_reset_block(hw)))
++ e1000_power_down_phy_copper(hw);
++
++ return;
++}
++
++/**
++ * e1000_clear_hw_cntrs_ich8lan - Clear statistical counters
++ * @hw: pointer to the HW structure
++ *
++ * Clears hardware counters specific to the silicon family and calls
++ * clear_hw_cntrs_generic to clear all general purpose counters.
++ **/
++static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
++{
++ u16 phy_data;
++
++ e1000e_clear_hw_cntrs_base(hw);
++
++ er32(ALGNERRC);
++ er32(RXERRC);
++ er32(TNCRS);
++ er32(CEXTERR);
++ er32(TSCTC);
++ er32(TSCTFC);
++
++ er32(MGTPRC);
++ er32(MGTPDC);
++ er32(MGTPTC);
++
++ er32(IAC);
++ er32(ICRXOC);
++
++ /* Clear PHY statistics registers */
++ if ((hw->phy.type == e1000_phy_82578) ||
++ (hw->phy.type == e1000_phy_82577)) {
++ e1e_rphy(hw, HV_SCC_UPPER, &phy_data);
++ e1e_rphy(hw, HV_SCC_LOWER, &phy_data);
++ e1e_rphy(hw, HV_ECOL_UPPER, &phy_data);
++ e1e_rphy(hw, HV_ECOL_LOWER, &phy_data);
++ e1e_rphy(hw, HV_MCC_UPPER, &phy_data);
++ e1e_rphy(hw, HV_MCC_LOWER, &phy_data);
++ e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data);
++ e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data);
++ e1e_rphy(hw, HV_COLC_UPPER, &phy_data);
++ e1e_rphy(hw, HV_COLC_LOWER, &phy_data);
++ e1e_rphy(hw, HV_DC_UPPER, &phy_data);
++ e1e_rphy(hw, HV_DC_LOWER, &phy_data);
++ e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data);
++ e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data);
++ }
++}
++
+diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.h linux-2.6.22-10/drivers/net/e1000e/e1000_ich8lan.h
+--- linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22-10/drivers/net/e1000e/e1000_ich8lan.h 2009-06-24 00:32:20.000000000 +0200
+@@ -0,0 +1,167 @@
++/*******************************************************************************
++
++ Intel PRO/1000 Linux driver
++ Copyright(c) 1999 - 2009 Intel Corporation.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms and conditions of the GNU General Public License,
++ version 2, as published by the Free Software Foundation.
++
++ This program is distributed in the hope it will be useful, but WITHOUT
++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ You should have received a copy of the GNU General Public License along with
++ this program; if not, write to the Free Software Foundation, Inc.,
++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++
++ The full GNU General Public License is included in this distribution in
++ the file called "COPYING".
++
++ Contact Information:
++ Linux NICS <linux.nics@intel.com>
++ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++
++*******************************************************************************/
++
++#ifndef _E1000_ICH8LAN_H_
++#define _E1000_ICH8LAN_H_
++
++#define ICH_FLASH_GFPREG 0x0000
++#define ICH_FLASH_HSFSTS 0x0004
++#define ICH_FLASH_HSFCTL 0x0006
++#define ICH_FLASH_FADDR 0x0008
++#define ICH_FLASH_FDATA0 0x0010
++
++/* Requires up to 10 seconds when MNG might be accessing part. */
++#define ICH_FLASH_READ_COMMAND_TIMEOUT 10000000
++#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 10000000
++#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 10000000
++#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF
++#define ICH_FLASH_CYCLE_REPEAT_COUNT 10
++
++#define ICH_CYCLE_READ 0
++#define ICH_CYCLE_WRITE 2
++#define ICH_CYCLE_ERASE 3
++
++#define FLASH_GFPREG_BASE_MASK 0x1FFF
++#define FLASH_SECTOR_ADDR_SHIFT 12
++
++#define ICH_FLASH_SEG_SIZE_256 256
++#define ICH_FLASH_SEG_SIZE_4K 4096
++#define ICH_FLASH_SEG_SIZE_8K 8192
++#define ICH_FLASH_SEG_SIZE_64K 65536
++#define ICH_FLASH_SECTOR_SIZE 4096
++
++#define ICH_FLASH_REG_MAPSIZE 0x00A0
++
++#define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */
++#define E1000_ICH_FWSM_DISSW 0x10000000 /* FW Disables SW Writes */
++/* FW established a valid mode */
++#define E1000_ICH_FWSM_FW_VALID 0x00008000
++
++#define E1000_ICH_MNG_IAMT_MODE 0x2
++
++#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \
++ (ID_LED_OFF1_OFF2 << 8) | \
++ (ID_LED_OFF1_ON2 << 4) | \
++ (ID_LED_DEF1_DEF2))
++
++#define E1000_ICH_NVM_SIG_WORD 0x13
++#define E1000_ICH_NVM_SIG_MASK 0xC000
++#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0
++#define E1000_ICH_NVM_SIG_VALUE 0x80
++
++#define E1000_ICH8_LAN_INIT_TIMEOUT 1500
++
++#define E1000_FEXTNVM_SW_CONFIG 1
++#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M */
++
++#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL
++
++#define E1000_ICH_RAR_ENTRIES 7
++
++#define PHY_PAGE_SHIFT 5
++#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
++ ((reg) & MAX_PHY_REG_ADDRESS))
++#define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */
++#define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */
++#define IGP3_CAPABILITY PHY_REG(776, 19) /* Capability */
++#define IGP3_PM_CTRL PHY_REG(769, 20) /* Power Management Control */
++
++#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002
++#define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300
++#define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200
++#define IGP3_PM_CTRL_FORCE_PWR_DOWN 0x0020
++
++/* PHY Wakeup Registers and defines */
++#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0)
++#define BM_WUC PHY_REG(BM_WUC_PAGE, 1)
++#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2)
++#define BM_WUS PHY_REG(BM_WUC_PAGE, 3)
++#define BM_RAR_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2)))
++#define BM_RAR_M(_i) (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2)))
++#define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2)))
++#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2)))
++#define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1)))
++
++#define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */
++#define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */
++#define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */
++#define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */
++#define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */
++#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */
++#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */
++
++#define HV_LED_CONFIG PHY_REG(768, 30) /* LED Configuration */
++#define HV_MUX_DATA_CTRL PHY_REG(776, 16)
++#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400
++#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004
++#define HV_SCC_UPPER PHY_REG(778, 16) /* Single Collision Count */
++#define HV_SCC_LOWER PHY_REG(778, 17)
++#define HV_ECOL_UPPER PHY_REG(778, 18) /* Excessive Collision Count */
++#define HV_ECOL_LOWER PHY_REG(778, 19)
++#define HV_MCC_UPPER PHY_REG(778, 20) /* Multiple Collision Count */
++#define HV_MCC_LOWER PHY_REG(778, 21)
++#define HV_LATECOL_UPPER PHY_REG(778, 23) /* Late Collision Count */
++#define HV_LATECOL_LOWER PHY_REG(778, 24)
++#define HV_COLC_UPPER PHY_REG(778, 25) /* Collision Count */
++#define HV_COLC_LOWER PHY_REG(778, 26)
++#define HV_DC_UPPER PHY_REG(778, 27) /* Defer Count */
++#define HV_DC_LOWER PHY_REG(778, 28)
++#define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */
++#define HV_TNCRS_LOWER PHY_REG(778, 30)
++
++/*
++ * Additional interrupts need to be handled for ICH family:
++ * DSW = The FW changed the status of the DISSW bit in FWSM
++ * PHYINT = The LAN connected device generates an interrupt
++ * EPRST = Manageability reset event
++ */
++#define IMS_ICH_ENABLE_MASK (\
++ E1000_IMS_DSW | \
++ E1000_IMS_PHYINT | \
++ E1000_IMS_EPRST)
++
++/* Additional interrupt register bit definitions */
++#define E1000_ICR_LSECPNC 0x00004000 /* PN threshold - client */
++#define E1000_IMS_LSECPNC E1000_ICR_LSECPNC /* PN threshold - client */
++#define E1000_ICS_LSECPNC E1000_ICR_LSECPNC /* PN threshold - client */
++
++/* Security Processing bit Indication */
++#define E1000_RXDEXT_LINKSEC_STATUS_LSECH 0x01000000
++#define E1000_RXDEXT_LINKSEC_ERROR_BIT_MASK 0x60000000
++#define E1000_RXDEXT_LINKSEC_ERROR_NO_SA_MATCH 0x20000000
++#define E1000_RXDEXT_LINKSEC_ERROR_REPLAY_ERROR 0x40000000
++#define E1000_RXDEXT_LINKSEC_ERROR_BAD_SIG 0x60000000
++
++
++void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
++ bool state);
++void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
++void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
++void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw);
++
++#endif
+diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers/net/e1000e/e1000_mac.c
+--- linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22-10/drivers/net/e1000e/e1000_mac.c 2009-06-24 00:32:20.000000000 +0200
+@@ -0,0 +1,1864 @@
++/*******************************************************************************
++
++ Intel PRO/1000 Linux driver
++ Copyright(c) 1999 - 2009 Intel Corporation.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms and conditions of the GNU General Public License,
++ version 2, as published by the Free Software Foundation.
++
++ This program is distributed in the hope it will be useful, but WITHOUT
++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ You should have received a copy of the GNU General Public License along with
++ this program; if not, write to the Free Software Foundation, Inc.,
++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++
++ The full GNU General Public License is included in this distribution in
++ the file called "COPYING".
++
++ Contact Information:
++ Linux NICS <linux.nics@intel.com>
++ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++
++*******************************************************************************/
++
++#include "e1000.h"
++
++static u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr);
++static s32 e1000_set_default_fc_generic(struct e1000_hw *hw);
++static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw);
++static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw);
++static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw);
++static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw);
++
++/**
++ * e1000_init_mac_ops_generic - Initialize MAC function pointers
++ * @hw: pointer to the HW structure
++ *
++ * Setups up the function pointers to no-op functions
++ **/
++void e1000_init_mac_ops_generic(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++ /* General Setup */
++ mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pcie;
++ mac->ops.read_mac_addr = e1000e_read_mac_addr_generic;
++ mac->ops.config_collision_dist = e1000e_config_collision_dist;
++ /* LINK */
++ mac->ops.wait_autoneg = e1000_wait_autoneg;
++ /* Management */
++ mac->ops.mng_host_if_write = e1000_mng_host_if_write_generic;
++ mac->ops.mng_write_cmd_header = e1000_mng_write_cmd_header_generic;
++ mac->ops.mng_enable_host_if = e1000_mng_enable_host_if_generic;
++ /* VLAN, MC, etc. */
++ mac->ops.rar_set = e1000e_rar_set;
++ mac->ops.validate_mdi_setting = e1000_validate_mdi_setting_generic;
++}
++
++/**
++ * e1000e_get_bus_info_pcie - Get PCIe bus information
++ * @hw: pointer to the HW structure
++ *
++ * Determines and stores the system bus information for a particular
++ * network interface. The following bus information is determined and stored:
++ * bus speed, bus width, type (PCIe), and PCIe function.
++ **/
++s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++ struct e1000_bus_info *bus = &hw->bus;
++
++ s32 ret_val;
++ u16 pcie_link_status;
++
++ bus->type = e1000_bus_type_pci_express;
++ bus->speed = e1000_bus_speed_2500;
++
++ ret_val = e1000_read_pcie_cap_reg(hw,
++ PCIE_LINK_STATUS,
++ &pcie_link_status);
++ if (ret_val)
++ bus->width = e1000_bus_width_unknown;
++ else
++ bus->width = (enum e1000_bus_width)((pcie_link_status &
++ PCIE_LINK_WIDTH_MASK) >>
++ PCIE_LINK_WIDTH_SHIFT);
++
++ mac->ops.set_lan_id(hw);
++
++ return E1000_SUCCESS;
++}
++
++/**
++ * e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
++ *
++ * @hw: pointer to the HW structure
++ *
++ * Determines the LAN function id by reading memory-mapped registers
++ * and swaps the port value if requested.
++ **/
++static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw)
++{
++ struct e1000_bus_info *bus = &hw->bus;
++ u32 reg;
++
++ /*
++ * The status register reports the correct function number
++ * for the device regardless of function swap state.
++ */
++ reg = er32(STATUS);
++ bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT;
++}
++
++/**
++ * e1000_set_lan_id_single_port - Set LAN id for a single port device
++ * @hw: pointer to the HW structure
++ *
++ * Sets the LAN function id to zero for a single port device.
++ **/
++void e1000_set_lan_id_single_port(struct e1000_hw *hw)
++{
++ struct e1000_bus_info *bus = &hw->bus;
++
++ bus->func = 0;
++}
++
++/**
++ * e1000e_clear_vfta_generic - Clear VLAN filter table
++ * @hw: pointer to the HW structure
++ *
++ * Clears the register array which contains the VLAN filter table by
++ * setting all the values to 0.
++ **/
++void e1000e_clear_vfta_generic(struct e1000_hw *hw)
++{
++ u32 offset;
++
++ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
++ E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0);
++ e1e_flush();
++ }
++}
++
++/**
++ * e1000e_write_vfta_generic - Write value to VLAN filter table
++ * @hw: pointer to the HW structure
++ * @offset: register offset in VLAN filter table
++ * @value: register value written to VLAN filter table
++ *
++ * Writes value at the given offset in the register array which stores
++ * the VLAN filter table.
++ **/
++void e1000e_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value)
++{
++ E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
++ e1e_flush();
++}
++
++/**
++ * e1000e_init_rx_addrs - Initialize receive address's
++ * @hw: pointer to the HW structure
++ * @rar_count: receive address registers
++ *
++ * Setups the receive address registers by setting the base receive address
++ * register to the devices MAC address and clearing all the other receive
++ * address registers to 0.
++ **/
++void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
++{
++ u32 i;
++ u8 mac_addr[ETH_ADDR_LEN] = {0};
++
++ /* Setup the receive address */
++ e_dbg("Programming MAC Address into RAR[0]\n");
++
++ hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
++
++ /* Zero out the other (rar_entry_count - 1) receive addresses */
++ e_dbg("Clearing RAR[1-%u]\n", rar_count-1);
++ for (i = 1; i < rar_count; i++)
++ hw->mac.ops.rar_set(hw, mac_addr, i);
++}
++
++/**
++ * e1000_check_alt_mac_addr_generic - Check for alternate MAC addr
++ * @hw: pointer to the HW structure
++ *
++ * Checks the nvm for an alternate MAC address. An alternate MAC address
++ * can be setup by pre-boot software and must be treated like a permanent
++ * address and must override the actual permanent MAC address. If an
++ * alternate MAC address is found it is programmed into RAR0, replacing
++ * the permanent address that was installed into RAR0 by the Si on reset.
++ * This function will return SUCCESS unless it encounters an error while
++ * reading the EEPROM.
++ **/
++s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
++{
++ u32 i;
++ s32 ret_val = E1000_SUCCESS;
++ u16 offset, nvm_alt_mac_addr_offset, nvm_data;
++ u8 alt_mac_addr[ETH_ADDR_LEN];
++
++ ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
++ &nvm_alt_mac_addr_offset);
++ if (ret_val) {
++ e_dbg("NVM Read Error\n");
++ goto out;
++ }
++
++ if (nvm_alt_mac_addr_offset == 0xFFFF) {
++ /* There is no Alternate MAC Address */
++ goto out;
++ }
++
++ if (hw->bus.func == E1000_FUNC_1)
++ nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
++ for (i = 0; i < ETH_ADDR_LEN; i += 2) {
++ offset = nvm_alt_mac_addr_offset + (i >> 1);
++ ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data);
++ if (ret_val) {
++ e_dbg("NVM Read Error\n");
++ goto out;
++ }
++
++ alt_mac_addr[i] = (u8)(nvm_data & 0xFF);
++ alt_mac_addr[i + 1] = (u8)(nvm_data >> 8);
++ }
++
++ /* if multicast bit is set, the alternate address will not be used */
++ if (alt_mac_addr[0] & 0x01) {
++ e_dbg("Ignoring Alternate Mac Address with MC bit set\n");
++ goto out;
++ }
++
++ /*
++ * We have a valid alternate MAC address, and we want to treat it the
++ * same as the normal permanent MAC address stored by the HW into the
++ * RAR. Do this by mapping this address into RAR0.
++ */
++ hw->mac.ops.rar_set(hw, alt_mac_addr, 0);
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_rar_set - Set receive address register
++ * @hw: pointer to the HW structure
++ * @addr: pointer to the receive address
++ * @index: receive address array register
++ *
++ * Sets the receive address array register at index to the address passed
++ * in by addr.
++ **/
++void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
++{
++ u32 rar_low, rar_high;
++
++ /*
++ * HW expects these in little endian so we reverse the byte order
++ * from network order (big endian) to little endian
++ */
++ rar_low = ((u32) addr[0] |
++ ((u32) addr[1] << 8) |
++ ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
++
++ rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
++
++ /* If MAC address zero, no need to set the AV bit */
++ if (rar_low || rar_high)
++ rar_high |= E1000_RAH_AV;
++
++ /*
++ * Some bridges will combine consecutive 32-bit writes into
++ * a single burst write, which will malfunction on some parts.
++ * The flushes avoid this.
++ */
++ ew32(RAL(index), rar_low);
++ e1e_flush();
++ ew32(RAH(index), rar_high);
++ e1e_flush();
++}
++
++/**
++ * e1000_mta_set_generic - Set multicast filter table address
++ * @hw: pointer to the HW structure
++ * @hash_value: determines the MTA register and bit to set
++ *
++ * The multicast table address is a register array of 32-bit registers.
++ * The hash_value is used to determine what register the bit is in, the
++ * current value is read, the new bit is OR'd in and the new value is
++ * written back into the register.
++ **/
++void e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value)
++{
++ u32 hash_bit, hash_reg, mta;
++
++ /*
++ * The MTA is a register array of 32-bit registers. It is
++ * treated like an array of (32*mta_reg_count) bits. We want to
++ * set bit BitArray[hash_value]. So we figure out what register
++ * the bit is in, read it, OR in the new bit, then write
++ * back the new value. The (hw->mac.mta_reg_count - 1) serves as a
++ * mask to bits 31:5 of the hash value which gives us the
++ * register we're modifying. The hash bit within that register
++ * is determined by the lower 5 bits of the hash value.
++ */
++ hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
++ hash_bit = hash_value & 0x1F;
++
++ mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg);
++
++ mta |= (1 << hash_bit);
++
++ E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta);
++ e1e_flush();
++}
++
++/**
++ * e1000e_update_mc_addr_list_generic - Update Multicast addresses
++ * @hw: pointer to the HW structure
++ * @mc_addr_list: array of multicast addresses to program
++ * @mc_addr_count: number of multicast addresses to program
++ *
++ * Updates entire Multicast Table Array.
++ * The caller must have a packed mc_addr_list of multicast addresses.
++ **/
++void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
++ u8 *mc_addr_list, u32 mc_addr_count)
++{
++ u32 hash_value, hash_bit, hash_reg;
++ int i;
++
++ /* clear mta_shadow */
++ memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
++
++ /* update mta_shadow from mc_addr_list */
++ for (i = 0; (u32) i < mc_addr_count; i++) {
++ hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list);
++
++ hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
++ hash_bit = hash_value & 0x1F;
++
++ hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
++ mc_addr_list += (ETH_ADDR_LEN);
++ }
++
++ /* replace the entire MTA table */
++ for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
++ E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]);
++ e1e_flush();
++}
++
++/**
++ * e1000_hash_mc_addr_generic - Generate a multicast hash value
++ * @hw: pointer to the HW structure
++ * @mc_addr: pointer to a multicast address
++ *
++ * Generates a multicast address hash value which is used to determine
++ * the multicast filter table array address and new table value. See
++ * e1000_mta_set_generic()
++ **/
++static u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr)
++{
++ u32 hash_value, hash_mask;
++ u8 bit_shift = 0;
++
++ /* Register count multiplied by bits per register */
++ hash_mask = (hw->mac.mta_reg_count * 32) - 1;
++
++ /*
++ * For a mc_filter_type of 0, bit_shift is the number of left-shifts
++ * where 0xFF would still fall within the hash mask.
++ */
++ while (hash_mask >> bit_shift != 0xFF)
++ bit_shift++;
++
++ /*
++ * The portion of the address that is used for the hash table
++ * is determined by the mc_filter_type setting.
++ * The algorithm is such that there is a total of 8 bits of shifting.
++ * The bit_shift for a mc_filter_type of 0 represents the number of
++ * left-shifts where the MSB of mc_addr[5] would still fall within
++ * the hash_mask. Case 0 does this exactly. Since there are a total
++ * of 8 bits of shifting, then mc_addr[4] will shift right the
++ * remaining number of bits. Thus 8 - bit_shift. The rest of the
++ * cases are a variation of this algorithm...essentially raising the
++ * number of bits to shift mc_addr[5] left, while still keeping the
++ * 8-bit shifting total.
++ *
++ * For example, given the following Destination MAC Address and an
++ * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask),
++ * we can see that the bit_shift for case 0 is 4. These are the hash
++ * values resulting from each mc_filter_type...
++ * [0] [1] [2] [3] [4] [5]
++ * 01 AA 00 12 34 56
++ * LSB MSB
++ *
++ * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563
++ * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6
++ * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163
++ * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634
++ */
++ switch (hw->mac.mc_filter_type) {
++ default:
++ case 0:
++ break;
++ case 1:
++ bit_shift += 1;
++ break;
++ case 2:
++ bit_shift += 2;
++ break;
++ case 3:
++ bit_shift += 4;
++ break;
++ }
++
++ hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
++ (((u16) mc_addr[5]) << bit_shift)));
++
++ return hash_value;
++}
++
++/**
++ * e1000e_clear_hw_cntrs_base - Clear base hardware counters
++ * @hw: pointer to the HW structure
++ *
++ * Clears the base hardware counters by reading the counter registers.
++ **/
++void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw)
++{
++ er32(CRCERRS);
++ er32(SYMERRS);
++ er32(MPC);
++ er32(SCC);
++ er32(ECOL);
++ er32(MCC);
++ er32(LATECOL);
++ er32(COLC);
++ er32(DC);
++ er32(SEC);
++ er32(RLEC);
++ er32(XONRXC);
++ er32(XONTXC);
++ er32(XOFFRXC);
++ er32(XOFFTXC);
++ er32(FCRUC);
++ er32(GPRC);
++ er32(BPRC);
++ er32(MPRC);
++ er32(GPTC);
++ er32(GORCL);
++ er32(GORCH);
++ er32(GOTCL);
++ er32(GOTCH);
++ er32(RNBC);
++ er32(RUC);
++ er32(RFC);
++ er32(ROC);
++ er32(RJC);
++ er32(TORL);
++ er32(TORH);
++ er32(TOTL);
++ er32(TOTH);
++ er32(TPR);
++ er32(TPT);
++ er32(MPTC);
++ er32(BPTC);
++}
++/**
++ * e1000e_check_for_copper_link - Check for link (Copper)
++ * @hw: pointer to the HW structure
++ *
++ * Checks to see of the link status of the hardware has changed. If a
++ * change in link status has been detected, then we read the PHY registers
++ * to get the current speed/duplex if link exists.
++ **/
++s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++ s32 ret_val;
++ bool link;
++
++ /*
++ * We only want to go out to the PHY registers to see if Auto-Neg
++ * has completed and/or if our link status has changed. The
++ * get_link_status flag is set upon receiving a Link Status
++ * Change or Rx Sequence Error interrupt.
++ */
++ if (!mac->get_link_status) {
++ ret_val = E1000_SUCCESS;
++ goto out;
++ }
++
++ /*
++ * First we want to see if the MII Status Register reports
++ * link. If so, then we want to get the current speed/duplex
++ * of the PHY.
++ */
++ ret_val = e1000e_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;
++
++ /*
++ * Check if there was DownShift, must be checked
++ * immediately after link-up
++ */
++ e1000e_check_downshift(hw);
++
++ /*
++ * If we are forcing speed/duplex, then we simply return since
++ * we have already determined whether we have link or not.
++ */
++ if (!mac->autoneg) {
++ ret_val = -E1000_ERR_CONFIG;
++ goto out;
++ }
++
++ /*
++ * Auto-Neg is enabled. Auto Speed Detection takes care
++ * of MAC speed/duplex configuration. So we only need to
++ * configure Collision Distance in the MAC.
++ */
++ e1000e_config_collision_dist(hw);
++
++ /*
++ * 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 = e1000e_config_fc_after_link_up(hw);
++ if (ret_val)
++ e_dbg("Error configuring flow control\n");
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_check_for_fiber_link - 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.
++ **/
++s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++ u32 rxcw;
++ u32 ctrl;
++ u32 status;
++ s32 ret_val = E1000_SUCCESS;
++
++ ctrl = er32(CTRL);
++ status = er32(STATUS);
++ rxcw = er32(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) == 1 == have signal */
++ if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) &&
++ (!(rxcw & E1000_RXCW_C))) {
++ if (mac->autoneg_failed == 0) {
++ mac->autoneg_failed = 1;
++ goto out;
++ }
++ e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n");
++
++ /* Disable auto-negotiation in the TXCW register */
++ ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
++
++ /* Force link-up and also force full-duplex. */
++ ctrl = er32(CTRL);
++ ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
++ ew32(CTRL, ctrl);
++
++ /* Configure Flow Control after forcing link up. */
++ ret_val = e1000e_config_fc_after_link_up(hw);
++ if (ret_val) {
++ e_dbg("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.
++ */
++ e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n");
++ ew32(TXCW, mac->txcw);
++ ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
++
++ mac->serdes_has_link = true;
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_check_for_serdes_link - Check for link (Serdes)
++ * @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.
++ **/
++s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++ u32 rxcw;
++ u32 ctrl;
++ u32 status;
++ s32 ret_val = E1000_SUCCESS;
++
++ ctrl = er32(CTRL);
++ status = er32(STATUS);
++ rxcw = er32(RXCW);
++
++ /*
++ * If we don't have link (auto-negotiation failed or link partner
++ * cannot auto-negotiate), 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.
++ */
++ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
++ if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
++ if (mac->autoneg_failed == 0) {
++ mac->autoneg_failed = 1;
++ goto out;
++ }
++ e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n");
++
++ /* Disable auto-negotiation in the TXCW register */
++ ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
++
++ /* Force link-up and also force full-duplex. */
++ ctrl = er32(CTRL);
++ ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
++ ew32(CTRL, ctrl);
++
++ /* Configure Flow Control after forcing link up. */
++ ret_val = e1000e_config_fc_after_link_up(hw);
++ if (ret_val) {
++ e_dbg("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.
++ */
++ e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n");
++ ew32(TXCW, mac->txcw);
++ ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
++
++ mac->serdes_has_link = true;
++ } else if (!(E1000_TXCW_ANE & er32(TXCW))) {
++ /*
++ * If we force link for non-auto-negotiation switch, check
++ * link status based on MAC synchronization for internal
++ * serdes media type.
++ */
++ /* SYNCH bit and IV bit are sticky. */
++ udelay(10);
++ rxcw = er32(RXCW);
++ if (rxcw & E1000_RXCW_SYNCH) {
++ if (!(rxcw & E1000_RXCW_IV)) {
++ mac->serdes_has_link = true;
++ e_dbg("SERDES: Link up - forced.\n");
++ }
++ } else {
++ mac->serdes_has_link = false;
++ e_dbg("SERDES: Link down - force failed.\n");
++ }
++ }
++
++ if (E1000_TXCW_ANE & er32(TXCW)) {
++ status = er32(STATUS);
++ if (status & E1000_STATUS_LU) {
++ /* SYNCH bit and IV bit are sticky, so reread rxcw. */
++ udelay(10);
++ rxcw = er32(RXCW);
++ if (rxcw & E1000_RXCW_SYNCH) {
++ if (!(rxcw & E1000_RXCW_IV)) {
++ mac->serdes_has_link = true;
++ e_dbg("SERDES: Link up - autoneg "
++ "completed sucessfully.\n");
++ } else {
++ mac->serdes_has_link = false;
++ e_dbg("SERDES: Link down - invalid"
++ "codewords detected in autoneg.\n");
++ }
++ } else {
++ mac->serdes_has_link = false;
++ e_dbg("SERDES: Link down - no sync.\n");
++ }
++ } else {
++ mac->serdes_has_link = false;
++ e_dbg("SERDES: Link down - autoneg failed\n");
++ }
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_setup_link - Setup flow control and link settings
++ * @hw: pointer to the HW structure
++ *
++ * 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.
++ **/
++s32 e1000e_setup_link(struct e1000_hw *hw)
++{
++ s32 ret_val = E1000_SUCCESS;
++
++ /*
++ * In the case of the phy reset being blocked, we already have a link.
++ * We do not need to set it up again.
++ */
++ if (hw->phy.ops.check_reset_block)
++ if (e1000_check_reset_block(hw))
++ goto out;
++
++ /*
++ * If requested flow control is set to default, set flow control
++ * based on the EEPROM flow control settings.
++ */
++ if (hw->fc.requested_mode == e1000_fc_default) {
++ ret_val = e1000_set_default_fc_generic(hw);
++ if (ret_val)
++ goto out;
++ }
++
++ /*
++ * Save off the requested flow control mode for use later. Depending
++ * on the link partner's capabilities, we may or may not use this mode.
++ */
++ hw->fc.current_mode = hw->fc.requested_mode;
++
++ e_dbg("After fix-ups FlowControl is now = %x\n",
++ hw->fc.current_mode);
++
++ /* Call the necessary media_type subroutine to configure the link. */
++ ret_val = hw->mac.ops.setup_physical_interface(hw);
++ if (ret_val)
++ goto out;
++
++ /*
++ * Initialize the flow control address, type, and PAUSE timer
++ * registers to their default values. This is done even if flow
++ * control is disabled, because it does not hurt anything to
++ * initialize these registers.
++ */
++ e_dbg("Initializing the Flow Control address, type and timer regs\n");
++ ew32(FCT, FLOW_CONTROL_TYPE);
++ ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
++ ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
++
++ ew32(FCTTV, hw->fc.pause_time);
++
++ ret_val = e1000e_set_fc_watermarks(hw);
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_setup_fiber_serdes_link - Setup link for fiber/serdes
++ * @hw: pointer to the HW structure
++ *
++ * Configures collision distance and flow control for fiber and serdes
++ * links. Upon successful setup, poll for link.
++ **/
++s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
++{
++ u32 ctrl;
++ s32 ret_val = E1000_SUCCESS;
++
++ ctrl = er32(CTRL);
++
++ /* Take the link out of reset */
++ ctrl &= ~E1000_CTRL_LRST;
++
++ e1000e_config_collision_dist(hw);
++
++ ret_val = e1000_commit_fc_settings_generic(hw);
++ if (ret_val)
++ goto out;
++
++ /*
++ * Since auto-negotiation is enabled, take the link out of reset (the
++ * link will be in reset, because we previously reset the chip). This
++ * will restart auto-negotiation. If auto-negotiation is successful
++ * then the link-up status bit will be set and the flow control enable
++ * bits (RFCE and TFCE) will be set according to their negotiated value.
++ */
++ e_dbg("Auto-negotiation enabled\n");
++
++ ew32(CTRL, ctrl);
++ e1e_flush();
++ msleep(1);
++
++ /*
++ * For these adapters, the SW definable pin 1 is set when the optics
++ * detect a signal. If we have a signal, then poll for a "Link-Up"
++ * indication.
++ */
++ if (hw->phy.media_type == e1000_media_type_internal_serdes ||
++ (er32(CTRL) & E1000_CTRL_SWDPIN1)) {
++ ret_val = e1000_poll_fiber_serdes_link_generic(hw);
++ } else {
++ e_dbg("No signal detected\n");
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_config_collision_dist - Configure collision distance
++ * @hw: pointer to the HW structure
++ *
++ * Configures the collision distance to the default value and is used
++ * during link setup. Currently no func pointer exists and all
++ * implementations are handled in the generic version of this function.
++ **/
++void e1000e_config_collision_dist(struct e1000_hw *hw)
++{
++ u32 tctl;
++
++ tctl = er32(TCTL);
++
++ tctl &= ~E1000_TCTL_COLD;
++ tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
++
++ ew32(TCTL, tctl);
++ e1e_flush();
++}
++
++/**
++ * e1000_poll_fiber_serdes_link_generic - Poll for link up
++ * @hw: pointer to the HW structure
++ *
++ * Polls for link up by reading the status register, if link fails to come
++ * up with auto-negotiation, then the link is forced if a signal is detected.
++ **/
++static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++ u32 i, status;
++ s32 ret_val = E1000_SUCCESS;
++
++ /*
++ * If we have a signal (the cable is plugged in, or assumed true for
++ * serdes media) then poll for a "Link-Up" indication in the Device
++ * Status Register. Time-out if a link isn't seen in 500 milliseconds
++ * seconds (Auto-negotiation should complete in less than 500
++ * milliseconds even if the other end is doing it in SW).
++ */
++ for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) {
++ msleep(10);
++ status = er32(STATUS);
++ if (status & E1000_STATUS_LU)
++ break;
++ }
++ if (i == FIBER_LINK_UP_LIMIT) {
++ e_dbg("Never got a valid link from auto-neg!!!\n");
++ mac->autoneg_failed = 1;
++ /*
++ * AutoNeg failed to achieve a link, so we'll call
++ * mac->check_for_link. This routine will force the
++ * link up if we detect a signal. This will allow us to
++ * communicate with non-autonegotiating link partners.
++ */
++ ret_val = hw->mac.ops.check_for_link(hw);
++ if (ret_val) {
++ e_dbg("Error while checking for link\n");
++ goto out;
++ }
++ mac->autoneg_failed = 0;
++ } else {
++ mac->autoneg_failed = 0;
++ e_dbg("Valid Link Found\n");
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_commit_fc_settings_generic - Configure flow control
++ * @hw: pointer to the HW structure
++ *
++ * Write the flow control settings to the Transmit Config Word Register (TXCW)
++ * base on the flow control settings in e1000_mac_info.
++ **/
++static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++ u32 txcw;
++ s32 ret_val = E1000_SUCCESS;
++
++ /*
++ * Check for a software override of the flow control settings, and
++ * setup the device accordingly. If auto-negotiation is enabled, then
++ * software will have to set the "PAUSE" bits to the correct value in
++ * the Transmit Config Word Register (TXCW) and re-start auto-
++ * negotiation. However, if auto-negotiation is disabled, then
++ * software will have to manually configure the two flow control enable
++ * bits in the CTRL register.
++ *
++ * The possible values of the "fc" parameter are:
++ * 0: Flow control is completely disabled
++ * 1: Rx flow control is enabled (we can receive pause frames,
++ * but not send pause frames).
++ * 2: Tx flow control is enabled (we can send pause frames but we
++ * do not support receiving pause frames).
++ * 3: Both Rx and Tx flow control (symmetric) are enabled.
++ */
++ switch (hw->fc.current_mode) {
++ case e1000_fc_none:
++ /* Flow control completely disabled by a software over-ride. */
++ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
++ break;
++ case e1000_fc_rx_pause:
++ /*
++ * Rx Flow control is enabled and Tx Flow control is disabled
++ * by a software over-ride. Since there really isn't a way to
++ * advertise that we are capable of Rx Pause ONLY, we will
++ * advertise that we support both symmetric and asymmetric RX
++ * PAUSE. Later, we will disable the adapter's ability to send
++ * PAUSE frames.
++ */
++ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
++ break;
++ case e1000_fc_tx_pause:
++ /*
++ * Tx Flow control is enabled, and Rx Flow control is disabled,
++ * by a software over-ride.
++ */
++ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
++ break;
++ case e1000_fc_full:
++ /*
++ * Flow control (both Rx and Tx) is enabled by a software
++ * over-ride.
++ */
++ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
++ break;
++ default:
++ e_dbg("Flow control param set incorrectly\n");
++ ret_val = -E1000_ERR_CONFIG;
++ goto out;
++ break;
++ }
++
++ ew32(TXCW, txcw);
++ mac->txcw = txcw;
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_set_fc_watermarks - Set flow control high/low watermarks
++ * @hw: pointer to the HW structure
++ *
++ * Sets the flow control high/low threshold (watermark) registers. If
++ * flow control XON frame transmission is enabled, then set XON frame
++ * transmission as well.
++ **/
++s32 e1000e_set_fc_watermarks(struct e1000_hw *hw)
++{
++ s32 ret_val = E1000_SUCCESS;
++ u32 fcrtl = 0, fcrth = 0;
++
++ /*
++ * Set the flow control receive threshold registers. Normally,
++ * these registers will be set to a default threshold that may be
++ * adjusted later by the driver's runtime code. However, if the
++ * ability to transmit pause frames is not enabled, then these
++ * registers will be set to 0.
++ */
++ if (hw->fc.current_mode & e1000_fc_tx_pause) {
++ /*
++ * We need to set up the Receive Threshold high and low water
++ * marks as well as (optionally) enabling the transmission of
++ * XON frames.
++ */
++ fcrtl = hw->fc.low_water;
++ if (hw->fc.send_xon)
++ fcrtl |= E1000_FCRTL_XONE;
++
++ fcrth = hw->fc.high_water;
++ }
++ ew32(FCRTL, fcrtl);
++ ew32(FCRTH, fcrth);
++
++ return ret_val;
++}
++
++/**
++ * e1000_set_default_fc_generic - Set flow control default values
++ * @hw: pointer to the HW structure
++ *
++ * Read the EEPROM for the default values for flow control and store the
++ * values.
++ **/
++static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
++{
++ s32 ret_val = E1000_SUCCESS;
++ u16 nvm_data;
++
++ /*
++ * Read and store word 0x0F of the EEPROM. This word contains bits
++ * that determine the hardware's default PAUSE (flow control) mode,
++ * a bit that determines whether the HW defaults to enabling or
++ * disabling auto-negotiation, and the direction of the
++ * SW defined pins. If there is no SW over-ride of the flow
++ * control setting, then the variable hw->fc will
++ * be initialized based on a value in the EEPROM.
++ */
++ ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
++
++ if (ret_val) {
++ e_dbg("NVM Read Error\n");
++ goto out;
++ }
++
++ if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
++ hw->fc.requested_mode = e1000_fc_none;
++ else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
++ NVM_WORD0F_ASM_DIR)
++ hw->fc.requested_mode = e1000_fc_tx_pause;
++ else
++ hw->fc.requested_mode = e1000_fc_full;
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_force_mac_fc - Force the MAC's flow control settings
++ * @hw: pointer to the HW structure
++ *
++ * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the
++ * device control register to reflect the adapter settings. TFCE and RFCE
++ * need to be explicitly set by software when a copper PHY is used because
++ * autonegotiation is managed by the PHY rather than the MAC. Software must
++ * also configure these bits when link is forced on a fiber connection.
++ **/
++s32 e1000e_force_mac_fc(struct e1000_hw *hw)
++{
++ u32 ctrl;
++ s32 ret_val = E1000_SUCCESS;
++
++ ctrl = er32(CTRL);
++
++ /*
++ * Because we didn't get link via the internal auto-negotiation
++ * mechanism (we either forced link or we got link via PHY
++ * auto-neg), we have to manually enable/disable transmit an
++ * receive flow control.
++ *
++ * The "Case" statement below enables/disable flow control
++ * according to the "hw->fc.current_mode" parameter.
++ *
++ * The possible values of the "fc" parameter are:
++ * 0: Flow control is completely disabled
++ * 1: Rx flow control is enabled (we can receive pause
++ * frames but not send pause frames).
++ * 2: Tx flow control is enabled (we can send pause frames
++ * frames but we do not receive pause frames).
++ * 3: Both Rx and Tx flow control (symmetric) is enabled.
++ * other: No other values should be possible at this point.
++ */
++ e_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode);
++
++ switch (hw->fc.current_mode) {
++ case e1000_fc_none:
++ ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
++ break;
++ case e1000_fc_rx_pause:
++ ctrl &= (~E1000_CTRL_TFCE);
++ ctrl |= E1000_CTRL_RFCE;
++ break;
++ case e1000_fc_tx_pause:
++ ctrl &= (~E1000_CTRL_RFCE);
++ ctrl |= E1000_CTRL_TFCE;
++ break;
++ case e1000_fc_full:
++ ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
++ break;
++ default:
++ e_dbg("Flow control param set incorrectly\n");
++ ret_val = -E1000_ERR_CONFIG;
++ goto out;
++ }
++
++ ew32(CTRL, ctrl);
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_config_fc_after_link_up - Configures flow control after link
++ * @hw: pointer to the HW structure
++ *
++ * Checks the status of auto-negotiation after link up to ensure that the
++ * speed and duplex were not forced. If the link needed to be forced, then
++ * flow control needs to be forced also. If auto-negotiation is enabled
++ * and did not fail, then we configure flow control based on our link
++ * partner.
++ **/
++s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++ s32 ret_val = E1000_SUCCESS;
++ u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
++ u16 speed, duplex;
++
++ /*
++ * Check for the case where we have fiber media and auto-neg failed
++ * so we had to force link. In this case, we need to force the
++ * configuration of the MAC to match the "fc" parameter.
++ */
++ if (mac->autoneg_failed) {
++ if (hw->phy.media_type == e1000_media_type_fiber ||
++ hw->phy.media_type == e1000_media_type_internal_serdes)
++ ret_val = e1000e_force_mac_fc(hw);
++ } else {
++ if (hw->phy.media_type == e1000_media_type_copper)
++ ret_val = e1000e_force_mac_fc(hw);
++ }
++
++ if (ret_val) {
++ e_dbg("Error forcing flow control settings\n");
++ goto out;
++ }
++
++ /*
++ * Check for the case where we have copper media and auto-neg is
++ * enabled. In this case, we need to check and see if Auto-Neg
++ * has completed, and if so, how the PHY and link partner has
++ * flow control configured.
++ */
++ if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) {
++ /*
++ * Read the MII Status Register and check to see if AutoNeg
++ * has completed. We read this twice because this reg has
++ * some "sticky" (latched) bits.
++ */
++ ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg);
++ if (ret_val)
++ goto out;
++ ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg);
++ if (ret_val)
++ goto out;
++
++ if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
++ e_dbg("Copper PHY and Auto Neg "
++ "has not completed.\n");
++ goto out;
++ }
++
++ /*
++ * The AutoNeg process has completed, so we now need to
++ * read both the Auto Negotiation Advertisement
++ * Register (Address 4) and the Auto_Negotiation Base
++ * Page Ability Register (Address 5) to determine how
++ * flow control was negotiated.
++ */
++ ret_val = e1e_rphy(hw, PHY_AUTONEG_ADV,
++ &mii_nway_adv_reg);
++ if (ret_val)
++ goto out;
++ ret_val = e1e_rphy(hw, PHY_LP_ABILITY,
++ &mii_nway_lp_ability_reg);
++ if (ret_val)
++ goto out;
++
++ /*
++ * Two bits in the Auto Negotiation Advertisement Register
++ * (Address 4) and two bits in the Auto Negotiation Base
++ * Page Ability Register (Address 5) determine flow control
++ * for both the PHY and the link partner. The following
++ * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
++ * 1999, describes these PAUSE resolution bits and how flow
++ * control is determined based upon these settings.
++ * NOTE: DC = Don't Care
++ *
++ * LOCAL DEVICE | LINK PARTNER
++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
++ *-------|---------|-------|---------|--------------------
++ * 0 | 0 | DC | DC | e1000_fc_none
++ * 0 | 1 | 0 | DC | e1000_fc_none
++ * 0 | 1 | 1 | 0 | e1000_fc_none
++ * 0 | 1 | 1 | 1 | e1000_fc_tx_pause
++ * 1 | 0 | 0 | DC | e1000_fc_none
++ * 1 | DC | 1 | DC | e1000_fc_full
++ * 1 | 1 | 0 | 0 | e1000_fc_none
++ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause
++ *
++ * Are both PAUSE bits set to 1? If so, this implies
++ * Symmetric Flow Control is enabled at both ends. The
++ * ASM_DIR bits are irrelevant per the spec.
++ *
++ * For Symmetric Flow Control:
++ *
++ * LOCAL DEVICE | LINK PARTNER
++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
++ *-------|---------|-------|---------|--------------------
++ * 1 | DC | 1 | DC | E1000_fc_full
++ *
++ */
++ if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
++ (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
++ /*
++ * Now we need to check if the user selected Rx ONLY
++ * of pause frames. In this case, we had to advertise
++ * FULL flow control because we could not advertise RX
++ * ONLY. Hence, we must now check to see if we need to
++ * turn OFF the TRANSMISSION of PAUSE frames.
++ */
++ if (hw->fc.requested_mode == e1000_fc_full) {
++ hw->fc.current_mode = e1000_fc_full;
++ e_dbg("Flow Control = FULL.\r\n");
++ } else {
++ hw->fc.current_mode = e1000_fc_rx_pause;
++ e_dbg("Flow Control = "
++ "RX PAUSE frames only.\r\n");
++ }
++ }
++ /*
++ * For receiving PAUSE frames ONLY.
++ *
++ * LOCAL DEVICE | LINK PARTNER
++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
++ *-------|---------|-------|---------|--------------------
++ * 0 | 1 | 1 | 1 | e1000_fc_tx_pause
++ */
++ else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
++ (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
++ (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
++ (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
++ hw->fc.current_mode = e1000_fc_tx_pause;
++ e_dbg("Flow Control = TX PAUSE frames only.\r\n");
++ }
++ /*
++ * For transmitting PAUSE frames ONLY.
++ *
++ * LOCAL DEVICE | LINK PARTNER
++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
++ *-------|---------|-------|---------|--------------------
++ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause
++ */
++ else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
++ (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
++ !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
++ (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
++ hw->fc.current_mode = e1000_fc_rx_pause;
++ e_dbg("Flow Control = RX PAUSE frames only.\r\n");
++ } else {
++ /*
++ * Per the IEEE spec, at this point flow control
++ * should be disabled.
++ */
++ hw->fc.current_mode = e1000_fc_none;
++ e_dbg("Flow Control = NONE.\r\n");
++ }
++
++ /*
++ * Now we need to do one last check... If we auto-
++ * negotiated to HALF DUPLEX, flow control should not be
++ * enabled per IEEE 802.3 spec.
++ */
++ ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
++ if (ret_val) {
++ e_dbg("Error getting link speed and duplex\n");
++ goto out;
++ }
++
++ if (duplex == HALF_DUPLEX)
++ hw->fc.current_mode = e1000_fc_none;
++
++ /*
++ * Now we call a subroutine to actually force the MAC
++ * controller to use the correct flow control settings.
++ */
++ ret_val = e1000e_force_mac_fc(hw);
++ if (ret_val) {
++ e_dbg("Error forcing flow control settings\n");
++ goto out;
++ }
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_get_speed_and_duplex_copper - Retrieve current speed/duplex
++ * @hw: pointer to the HW structure
++ * @speed: stores the current speed
++ * @duplex: stores the current duplex
++ *
++ * Read the status register for the current speed/duplex and store the current
++ * speed and duplex for copper connections.
++ **/
++s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed,
++ u16 *duplex)
++{
++ u32 status;
++
++ status = er32(STATUS);
++ if (status & E1000_STATUS_SPEED_1000) {
++ *speed = SPEED_1000;
++ e_dbg("1000 Mbs, ");
++ } else if (status & E1000_STATUS_SPEED_100) {
++ *speed = SPEED_100;
++ e_dbg("100 Mbs, ");
++ } else {
++ *speed = SPEED_10;
++ e_dbg("10 Mbs, ");
++ }
++
++ if (status & E1000_STATUS_FD) {
++ *duplex = FULL_DUPLEX;
++ e_dbg("Full Duplex\n");
++ } else {
++ *duplex = HALF_DUPLEX;
++ e_dbg("Half Duplex\n");
++ }
++
++ return E1000_SUCCESS;
++}
++
++/**
++ * e1000_get_speed_and_duplex_fiber_generic - Retrieve current speed/duplex
++ * @hw: pointer to the HW structure
++ * @speed: stores the current speed
++ * @duplex: stores the current duplex
++ *
++ * Sets the speed and duplex to gigabit full duplex (the only possible option)
++ * for fiber/serdes links.
++ **/
++s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw,
++ u16 *speed, u16 *duplex)
++{
++ *speed = SPEED_1000;
++ *duplex = FULL_DUPLEX;
++
++ return E1000_SUCCESS;
++}
++
++/**
++ * e1000e_get_hw_semaphore - Acquire hardware semaphore
++ * @hw: pointer to the HW structure
++ *
++ * Acquire the HW semaphore to access the PHY or NVM
++ **/
++s32 e1000e_get_hw_semaphore(struct e1000_hw *hw)
++{
++ u32 swsm;
++ s32 ret_val = E1000_SUCCESS;
++ s32 timeout = hw->nvm.word_size + 1;
++ s32 i = 0;
++
++ /* Get the SW semaphore */
++ while (i < timeout) {
++ swsm = er32(SWSM);
++ if (!(swsm & E1000_SWSM_SMBI))
++ break;
++
++ udelay(50);
++ i++;
++ }
++
++ if (i == timeout) {
++ e_dbg("Driver can't access device - SMBI bit is set.\n");
++ ret_val = -E1000_ERR_NVM;
++ goto out;
++ }
++
++ /* Get the FW semaphore. */
++ for (i = 0; i < timeout; i++) {
++ swsm = er32(SWSM);
++ ew32(SWSM, swsm | E1000_SWSM_SWESMBI);
++
++ /* Semaphore acquired if bit latched */
++ if (er32(SWSM) & E1000_SWSM_SWESMBI)
++ break;
++
++ udelay(50);
++ }
++
++ if (i == timeout) {
++ /* Release semaphores */
++ e1000e_put_hw_semaphore(hw);
++ e_dbg("Driver can't access the NVM\n");
++ ret_val = -E1000_ERR_NVM;
++ goto out;
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_put_hw_semaphore - Release hardware semaphore
++ * @hw: pointer to the HW structure
++ *
++ * Release hardware semaphore used to access the PHY or NVM
++ **/
++void e1000e_put_hw_semaphore(struct e1000_hw *hw)
++{
++ u32 swsm;
++
++ swsm = er32(SWSM);
++ swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
++ ew32(SWSM, swsm);
++}
++/**
++ * e1000e_get_auto_rd_done - Check for auto read completion
++ * @hw: pointer to the HW structure
++ *
++ * Check EEPROM for Auto Read done bit.
++ **/
++s32 e1000e_get_auto_rd_done(struct e1000_hw *hw)
++{
++ s32 i = 0;
++ s32 ret_val = E1000_SUCCESS;
++
++ while (i < AUTO_READ_DONE_TIMEOUT) {
++ if (er32(EECD) & E1000_EECD_AUTO_RD)
++ break;
++ msleep(1);
++ i++;
++ }
++
++ if (i == AUTO_READ_DONE_TIMEOUT) {
++ e_dbg("Auto read by HW from NVM has not completed.\n");
++ ret_val = -E1000_ERR_RESET;
++ goto out;
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_valid_led_default - Verify a valid default LED config
++ * @hw: pointer to the HW structure
++ * @data: pointer to the NVM (EEPROM)
++ *
++ * Read the EEPROM for the current default LED configuration. If the
++ * LED configuration is not valid, set to a valid LED configuration.
++ **/
++s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data)
++{
++ s32 ret_val;
++
++ ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data);
++ if (ret_val) {
++ e_dbg("NVM Read Error\n");
++ goto out;
++ }
++
++ if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
++ *data = ID_LED_DEFAULT;
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_id_led_init -
++ * @hw: pointer to the HW structure
++ *
++ **/
++s32 e1000e_id_led_init(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++ s32 ret_val;
++ const u32 ledctl_mask = 0x000000FF;
++ const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;
++ const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
++ u16 data, i, temp;
++ const u16 led_mask = 0x0F;
++
++ ret_val = hw->nvm.ops.valid_led_default(hw, &data);
++ if (ret_val)
++ goto out;
++
++ mac->ledctl_default = er32(LEDCTL);
++ mac->ledctl_mode1 = mac->ledctl_default;
++ mac->ledctl_mode2 = mac->ledctl_default;
++
++ for (i = 0; i < 4; i++) {
++ temp = (data >> (i << 2)) & led_mask;
++ switch (temp) {
++ case ID_LED_ON1_DEF2:
++ case ID_LED_ON1_ON2:
++ case ID_LED_ON1_OFF2:
++ mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
++ mac->ledctl_mode1 |= ledctl_on << (i << 3);
++ break;
++ case ID_LED_OFF1_DEF2:
++ case ID_LED_OFF1_ON2:
++ case ID_LED_OFF1_OFF2:
++ mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
++ mac->ledctl_mode1 |= ledctl_off << (i << 3);
++ break;
++ default:
++ /* Do nothing */
++ break;
++ }
++ switch (temp) {
++ case ID_LED_DEF1_ON2:
++ case ID_LED_ON1_ON2:
++ case ID_LED_OFF1_ON2:
++ mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
++ mac->ledctl_mode2 |= ledctl_on << (i << 3);
++ break;
++ case ID_LED_DEF1_OFF2:
++ case ID_LED_ON1_OFF2:
++ case ID_LED_OFF1_OFF2:
++ mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
++ mac->ledctl_mode2 |= ledctl_off << (i << 3);
++ break;
++ default:
++ /* Do nothing */
++ break;
++ }
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_setup_led_generic - Configures SW controllable LED
++ * @hw: pointer to the HW structure
++ *
++ * This prepares the SW controllable LED for use and saves the current state
++ * of the LED so it can be later restored.
++ **/
++s32 e1000_setup_led_generic(struct e1000_hw *hw)
++{
++ u32 ledctl;
++ s32 ret_val = E1000_SUCCESS;
++
++ if (hw->mac.ops.setup_led != e1000_setup_led_generic) {
++ ret_val = -E1000_ERR_CONFIG;
++ goto out;
++ }
++
++ if (hw->phy.media_type == e1000_media_type_fiber) {
++ ledctl = er32(LEDCTL);
++ hw->mac.ledctl_default = ledctl;
++ /* Turn off LED0 */
++ ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
++ E1000_LEDCTL_LED0_BLINK |
++ E1000_LEDCTL_LED0_MODE_MASK);
++ ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
++ E1000_LEDCTL_LED0_MODE_SHIFT);
++ ew32(LEDCTL, ledctl);
++ } else if (hw->phy.media_type == e1000_media_type_copper) {
++ ew32(LEDCTL, hw->mac.ledctl_mode1);
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_cleanup_led_generic - Set LED config to default operation
++ * @hw: pointer to the HW structure
++ *
++ * Remove the current LED configuration and set the LED configuration
++ * to the default value, saved from the EEPROM.
++ **/
++s32 e1000e_cleanup_led_generic(struct e1000_hw *hw)
++{
++ s32 ret_val = E1000_SUCCESS;
++
++ if (hw->mac.ops.cleanup_led != e1000e_cleanup_led_generic) {
++ ret_val = -E1000_ERR_CONFIG;
++ goto out;
++ }
++
++ ew32(LEDCTL, hw->mac.ledctl_default);
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_blink_led - Blink LED
++ * @hw: pointer to the HW structure
++ *
++ * Blink the LEDs which are set to be on.
++ **/
++s32 e1000e_blink_led(struct e1000_hw *hw)
++{
++ u32 ledctl_blink = 0;
++ u32 i;
++
++ if (hw->phy.media_type == e1000_media_type_fiber) {
++ /* always blink LED0 for PCI-E fiber */
++ ledctl_blink = E1000_LEDCTL_LED0_BLINK |
++ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
++ } else {
++ /*
++ * set the blink bit for each LED that's "on" (0x0E)
++ * in ledctl_mode2
++ */
++ ledctl_blink = hw->mac.ledctl_mode2;
++ for (i = 0; i < 4; i++)
++ if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
++ E1000_LEDCTL_MODE_LED_ON)
++ ledctl_blink |= (E1000_LEDCTL_LED0_BLINK <<
++ (i * 8));
++ }
++
++ ew32(LEDCTL, ledctl_blink);
++
++ return E1000_SUCCESS;
++}
++
++/**
++ * e1000e_led_on_generic - Turn LED on
++ * @hw: pointer to the HW structure
++ *
++ * Turn LED on.
++ **/
++s32 e1000e_led_on_generic(struct e1000_hw *hw)
++{
++ u32 ctrl;
++
++ switch (hw->phy.media_type) {
++ case e1000_media_type_fiber:
++ ctrl = er32(CTRL);
++ ctrl &= ~E1000_CTRL_SWDPIN0;
++ ctrl |= E1000_CTRL_SWDPIO0;
++ ew32(CTRL, ctrl);
++ break;
++ case e1000_media_type_copper:
++ ew32(LEDCTL, hw->mac.ledctl_mode2);
++ break;
++ default:
++ break;
++ }
++
++ return E1000_SUCCESS;
++}
++
++/**
++ * e1000e_led_off_generic - Turn LED off
++ * @hw: pointer to the HW structure
++ *
++ * Turn LED off.
++ **/
++s32 e1000e_led_off_generic(struct e1000_hw *hw)
++{
++ u32 ctrl;
++
++ switch (hw->phy.media_type) {
++ case e1000_media_type_fiber:
++ ctrl = er32(CTRL);
++ ctrl |= E1000_CTRL_SWDPIN0;
++ ctrl |= E1000_CTRL_SWDPIO0;
++ ew32(CTRL, ctrl);
++ break;
++ case e1000_media_type_copper:
++ ew32(LEDCTL, hw->mac.ledctl_mode1);
++ break;
++ default:
++ break;
++ }
++
++ return E1000_SUCCESS;
++}
++
++/**
++ * e1000e_set_pcie_no_snoop - Set PCI-express capabilities
++ * @hw: pointer to the HW structure
++ * @no_snoop: bitmap of snoop events
++ *
++ * Set the PCI-express register to snoop for events enabled in 'no_snoop'.
++ **/
++void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop)
++{
++ u32 gcr;
++
++ if (hw->bus.type != e1000_bus_type_pci_express)
++ goto out;
++
++ if (no_snoop) {
++ gcr = er32(GCR);
++ gcr &= ~(PCIE_NO_SNOOP_ALL);
++ gcr |= no_snoop;
++ ew32(GCR, gcr);
++ }
++out:
++ return;
++}
++
++/**
++ * e1000e_disable_pcie_master - Disables PCI-express master access
++ * @hw: pointer to the HW structure
++ *
++ * Returns 0 (E1000_SUCCESS) if successful, else returns -10
++ * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused
++ * the master requests to be disabled.
++ *
++ * Disables PCI-Express master access and verifies there are no pending
++ * requests.
++ **/
++s32 e1000e_disable_pcie_master(struct e1000_hw *hw)
++{
++ u32 ctrl;
++ s32 timeout = MASTER_DISABLE_TIMEOUT;
++ s32 ret_val = E1000_SUCCESS;
++
++ if (hw->bus.type != e1000_bus_type_pci_express)
++ goto out;
++
++ ctrl = er32(CTRL);
++ ctrl |= E1000_CTRL_GIO_MASTER_DISABLE;
++ ew32(CTRL, ctrl);
++
++ while (timeout) {
++ if (!(er32(STATUS) &
++ E1000_STATUS_GIO_MASTER_ENABLE))
++ break;
++ udelay(100);
++ timeout--;
++ }
++
++ if (!timeout) {
++ e_dbg("Master requests are pending.\n");
++ ret_val = -E1000_ERR_MASTER_REQUESTS_PENDING;
++ goto out;
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_reset_adaptive - Reset Adaptive Interframe Spacing
++ * @hw: pointer to the HW structure
++ *
++ * Reset the Adaptive Interframe Spacing throttle to default values.
++ **/
++void e1000e_reset_adaptive(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++
++ if (!mac->adaptive_ifs) {
++ e_dbg("Not in Adaptive IFS mode!\n");
++ goto out;
++ }
++
++ mac->current_ifs_val = 0;
++ mac->ifs_min_val = IFS_MIN;
++ mac->ifs_max_val = IFS_MAX;
++ mac->ifs_step_size = IFS_STEP;
++ mac->ifs_ratio = IFS_RATIO;
++
++ mac->in_ifs_mode = false;
++ ew32(AIT, 0);
++out:
++ return;
++}
++
++/**
++ * e1000e_update_adaptive - Update Adaptive Interframe Spacing
++ * @hw: pointer to the HW structure
++ *
++ * Update the Adaptive Interframe Spacing Throttle value based on the
++ * time between transmitted packets and time between collisions.
++ **/
++void e1000e_update_adaptive(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++
++ if (!mac->adaptive_ifs) {
++ e_dbg("Not in Adaptive IFS mode!\n");
++ goto out;
++ }
++
++ if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) {
++ if (mac->tx_packet_delta > MIN_NUM_XMITS) {
++ mac->in_ifs_mode = true;
++ if (mac->current_ifs_val < mac->ifs_max_val) {
++ if (!mac->current_ifs_val)
++ mac->current_ifs_val = mac->ifs_min_val;
++ else
++ mac->current_ifs_val +=
++ mac->ifs_step_size;
++ ew32(AIT, mac->current_ifs_val);
++ }
++ }
++ } else {
++ if (mac->in_ifs_mode &&
++ (mac->tx_packet_delta <= MIN_NUM_XMITS)) {
++ mac->current_ifs_val = 0;
++ mac->in_ifs_mode = false;
++ ew32(AIT, 0);
++ }
++ }
++out:
++ return;
++}
++
++/**
++ * e1000_validate_mdi_setting_generic - Verify MDI/MDIx settings
++ * @hw: pointer to the HW structure
++ *
++ * Verify that when not using auto-negotiation that MDI/MDIx is correctly
++ * set, which is forced to MDI mode only.
++ **/
++s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw)
++{
++ s32 ret_val = E1000_SUCCESS;
++
++ if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) {
++ e_dbg("Invalid MDI setting detected\n");
++ hw->phy.mdix = 1;
++ ret_val = -E1000_ERR_CONFIG;
++ goto out;
++ }
++
++out:
++ return ret_val;
++}
+diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.h linux-2.6.22-10/drivers/net/e1000e/e1000_mac.h
+--- linux-2.6.22-0/drivers/net/e1000e/e1000_mac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22-10/drivers/net/e1000e/e1000_mac.h 2009-06-24 00:32:20.000000000 +0200
+@@ -0,0 +1,77 @@
++/*******************************************************************************
++
++ Intel PRO/1000 Linux driver
++ Copyright(c) 1999 - 2009 Intel Corporation.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms and conditions of the GNU General Public License,
++ version 2, as published by the Free Software Foundation.
++
++ This program is distributed in the hope it will be useful, but WITHOUT
++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ You should have received a copy of the GNU General Public License along with
++ this program; if not, write to the Free Software Foundation, Inc.,
++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++
++ The full GNU General Public License is included in this distribution in
++ the file called "COPYING".
++
++ Contact Information:
++ Linux NICS <linux.nics@intel.com>
++ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++
++*******************************************************************************/
++
++#ifndef _E1000_MAC_H_
++#define _E1000_MAC_H_
++
++/*
++ * Functions that should not be called directly from drivers but can be used
++ * by other files in this 'shared code'
++ */
++void e1000_init_mac_ops_generic(struct e1000_hw *hw);
++s32 e1000e_blink_led(struct e1000_hw *hw);
++s32 e1000e_check_for_copper_link(struct e1000_hw *hw);
++s32 e1000e_check_for_fiber_link(struct e1000_hw *hw);
++s32 e1000e_check_for_serdes_link(struct e1000_hw *hw);
++s32 e1000e_cleanup_led_generic(struct e1000_hw *hw);
++s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw);
++s32 e1000e_disable_pcie_master(struct e1000_hw *hw);
++s32 e1000e_force_mac_fc(struct e1000_hw *hw);
++s32 e1000e_get_auto_rd_done(struct e1000_hw *hw);
++s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw);
++void e1000_set_lan_id_single_port(struct e1000_hw *hw);
++s32 e1000e_get_hw_semaphore(struct e1000_hw *hw);
++s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed,
++ u16 *duplex);
++s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw,
++ u16 *speed, u16 *duplex);
++s32 e1000e_id_led_init(struct e1000_hw *hw);
++s32 e1000e_led_on_generic(struct e1000_hw *hw);
++s32 e1000e_led_off_generic(struct e1000_hw *hw);
++void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
++ u8 *mc_addr_list, u32 mc_addr_count);
++s32 e1000e_set_fc_watermarks(struct e1000_hw *hw);
++s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw);
++s32 e1000_setup_led_generic(struct e1000_hw *hw);
++s32 e1000e_setup_link(struct e1000_hw *hw);
++
++void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw);
++void e1000e_clear_vfta_generic(struct e1000_hw *hw);
++void e1000e_config_collision_dist(struct e1000_hw *hw);
++void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
++void e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value);
++void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw);
++void e1000e_put_hw_semaphore(struct e1000_hw *hw);
++void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
++s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw);
++void e1000e_reset_adaptive(struct e1000_hw *hw);
++void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop);
++void e1000e_update_adaptive(struct e1000_hw *hw);
++void e1000e_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value);
++
++#endif
+diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/drivers/net/e1000e/e1000_manage.c
+--- linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22-10/drivers/net/e1000e/e1000_manage.c 2009-06-24 00:32:20.000000000 +0200
+@@ -0,0 +1,365 @@
++/*******************************************************************************
++
++ Intel PRO/1000 Linux driver
++ Copyright(c) 1999 - 2009 Intel Corporation.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms and conditions of the GNU General Public License,
++ version 2, as published by the Free Software Foundation.
++
++ This program is distributed in the hope it will be useful, but WITHOUT
++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ You should have received a copy of the GNU General Public License along with
++ this program; if not, write to the Free Software Foundation, Inc.,
++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++
++ The full GNU General Public License is included in this distribution in
++ the file called "COPYING".
++
++ Contact Information:
++ Linux NICS <linux.nics@intel.com>
++ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++
++*******************************************************************************/
++
++#include "e1000.h"
++
++static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
++
++/**
++ * e1000_calculate_checksum - Calculate checksum for buffer
++ * @buffer: pointer to EEPROM
++ * @length: size of EEPROM to calculate a checksum for
++ *
++ * Calculates the checksum for some buffer on a specified length. The
++ * checksum calculated is returned.
++ **/
++static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
++{
++ u32 i;
++ u8 sum = 0;
++
++ if (!buffer)
++ return 0;
++ for (i = 0; i < length; i++)
++ sum += buffer[i];
++
++ return (u8) (0 - sum);
++}
++
++/**
++ * e1000_mng_enable_host_if_generic - Checks host interface is enabled
++ * @hw: pointer to the HW structure
++ *
++ * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
++ *
++ * This function checks whether the HOST IF is enabled for command operation
++ * and also checks whether the previous command is completed. It busy waits
++ * in case of previous command is not completed.
++ **/
++s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
++{
++ u32 hicr;
++ s32 ret_val = E1000_SUCCESS;
++ u8 i;
++
++ /* Check that the host interface is enabled. */
++ hicr = er32(HICR);
++ if ((hicr & E1000_HICR_EN) == 0) {
++ e_dbg("E1000_HOST_EN bit disabled.\n");
++ ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
++ goto out;
++ }
++ /* check the previous command is completed */
++ for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
++ hicr = er32(HICR);
++ if (!(hicr & E1000_HICR_C))
++ break;
++ mdelay(1);
++ }
++
++ if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
++ e_dbg("Previous command timeout failed .\n");
++ ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
++ goto out;
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_check_mng_mode_generic - Generic check management mode
++ * @hw: pointer to the HW structure
++ *
++ * Reads the firmware semaphore register and returns true (>0) if
++ * manageability is enabled, else false (0).
++ **/
++bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
++{
++ u32 fwsm;
++
++ fwsm = er32(FWSM);
++ return (fwsm & E1000_FWSM_MODE_MASK) ==
++ (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
++}
++/**
++ * e1000e_enable_tx_pkt_filtering - Enable packet filtering on TX
++ * @hw: pointer to the HW structure
++ *
++ * Enables packet filtering on transmit packets if manageability is enabled
++ * and host interface is enabled.
++ **/
++bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
++{
++ struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
++ u32 *buffer = (u32 *)&hw->mng_cookie;
++ u32 offset;
++ s32 ret_val, hdr_csum, csum;
++ u8 i, len;
++ bool tx_filter = true;
++
++ /* No manageability, no filtering */
++ if (!hw->mac.ops.check_mng_mode(hw)) {
++ tx_filter = false;
++ goto out;
++ }
++
++ /*
++ * If we can't read from the host interface for whatever
++ * reason, disable filtering.
++ */
++ ret_val = hw->mac.ops.mng_enable_host_if(hw);
++ if (ret_val != E1000_SUCCESS) {
++ tx_filter = false;
++ goto out;
++ }
++
++ /* Read in the header. Length and offset are in dwords. */
++ len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
++ offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
++ for (i = 0; i < len; i++) {
++ *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
++ E1000_HOST_IF,
++ offset + i);
++ }
++ hdr_csum = hdr->checksum;
++ hdr->checksum = 0;
++ csum = e1000_calculate_checksum((u8 *)hdr,
++ E1000_MNG_DHCP_COOKIE_LENGTH);
++ /*
++ * If either the checksums or signature don't match, then
++ * the cookie area isn't considered valid, in which case we
++ * take the safe route of assuming Tx filtering is enabled.
++ */
++ if (hdr_csum != csum)
++ goto out;
++ if (hdr->signature != E1000_IAMT_SIGNATURE)
++ goto out;
++
++ /* Cookie area is valid, make the final check for filtering. */
++ if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
++ tx_filter = false;
++
++out:
++ hw->mac.tx_pkt_filtering = tx_filter;
++ return tx_filter;
++}
++
++/**
++ * e1000e_mng_write_dhcp_info - Writes DHCP info to host interface
++ * @hw: pointer to the HW structure
++ * @buffer: pointer to the host interface
++ * @length: size of the buffer
++ *
++ * Writes the DHCP information to the host interface.
++ **/
++s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer,
++ u16 length)
++{
++ struct e1000_host_mng_command_header hdr;
++ s32 ret_val;
++ u32 hicr;
++
++ hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
++ hdr.command_length = length;
++ hdr.reserved1 = 0;
++ hdr.reserved2 = 0;
++ hdr.checksum = 0;
++
++ /* Enable the host interface */
++ ret_val = hw->mac.ops.mng_enable_host_if(hw);
++ if (ret_val)
++ goto out;
++
++ /* Populate the host interface with the contents of "buffer". */
++ ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
++ sizeof(hdr), &(hdr.checksum));
++ if (ret_val)
++ goto out;
++
++ /* Write the manageability command header */
++ ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
++ if (ret_val)
++ goto out;
++
++ /* Tell the ARC a new command is pending. */
++ hicr = er32(HICR);
++ ew32(HICR, hicr | E1000_HICR_C);
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_mng_write_cmd_header_generic - Writes manageability command header
++ * @hw: pointer to the HW structure
++ * @hdr: pointer to the host interface command header
++ *
++ * Writes the command header after does the checksum calculation.
++ **/
++s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
++ struct e1000_host_mng_command_header *hdr)
++{
++ u16 i, length = sizeof(struct e1000_host_mng_command_header);
++
++ /* Write the whole command header structure with new checksum. */
++
++ hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
++
++ length >>= 2;
++ /* Write the relevant command block into the ram area. */
++ for (i = 0; i < length; i++) {
++ E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
++ *((u32 *) hdr + i));
++ e1e_flush();
++ }
++
++ return E1000_SUCCESS;
++}
++
++/**
++ * e1000_mng_host_if_write_generic - Write to the manageability host interface
++ * @hw: pointer to the HW structure
++ * @buffer: pointer to the host interface buffer
++ * @length: size of the buffer
++ * @offset: location in the buffer to write to
++ * @sum: sum of the data (not checksum)
++ *
++ * This function writes the buffer content at the offset given on the host if.
++ * It also does alignment considerations to do the writes in most efficient
++ * way. Also fills up the sum of the buffer in *buffer parameter.
++ **/
++s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
++ u16 length, u16 offset, u8 *sum)
++{
++ u8 *tmp;
++ u8 *bufptr = buffer;
++ u32 data = 0;
++ s32 ret_val = E1000_SUCCESS;
++ u16 remaining, i, j, prev_bytes;
++
++ /* sum = only sum of the data and it is not checksum */
++
++ if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
++ ret_val = -E1000_ERR_PARAM;
++ goto out;
++ }
++
++ tmp = (u8 *)&data;
++ prev_bytes = offset & 0x3;
++ offset >>= 2;
++
++ if (prev_bytes) {
++ data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
++ for (j = prev_bytes; j < sizeof(u32); j++) {
++ *(tmp + j) = *bufptr++;
++ *sum += *(tmp + j);
++ }
++ E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
++ length -= j - prev_bytes;
++ offset++;
++ }
++
++ remaining = length & 0x3;
++ length -= remaining;
++
++ /* Calculate length in DWORDs */
++ length >>= 2;
++
++ /*
++ * The device driver writes the relevant command block into the
++ * ram area.
++ */
++ for (i = 0; i < length; i++) {
++ for (j = 0; j < sizeof(u32); j++) {
++ *(tmp + j) = *bufptr++;
++ *sum += *(tmp + j);
++ }
++
++ E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
++ data);
++ }
++ if (remaining) {
++ for (j = 0; j < sizeof(u32); j++) {
++ if (j < remaining)
++ *(tmp + j) = *bufptr++;
++ else
++ *(tmp + j) = 0;
++
++ *sum += *(tmp + j);
++ }
++ E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000e_enable_mng_pass_thru - Enable processing of ARP's
++ * @hw: pointer to the HW structure
++ *
++ * Verifies the hardware needs to allow ARPs to be processed by the host.
++ **/
++bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
++{
++ u32 manc;
++ u32 fwsm, factps;
++ bool ret_val = false;
++
++ if (!hw->mac.asf_firmware_present)
++ goto out;
++
++ manc = er32(MANC);
++
++ if (!(manc & E1000_MANC_RCV_TCO_EN) ||
++ !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
++ goto out;
++
++ if (hw->mac.arc_subsystem_valid) {
++ fwsm = er32(FWSM);
++ factps = er32(FACTPS);
++
++ if (!(factps & E1000_FACTPS_MNGCG) &&
++ ((fwsm & E1000_FWSM_MODE_MASK) ==
++ (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
++ ret_val = true;
++ goto out;
++ }
++ } else {
++ if ((manc & E1000_MANC_SMBUS_EN) &&
++ !(manc & E1000_MANC_ASF_EN)) {
++ ret_val = true;
++ goto out;
++ }
++ }
++
++out:
++ return ret_val;
++}
++
+diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.h linux-2.6.22-10/drivers/net/e1000e/e1000_manage.h
+--- linux-2.6.22-0/drivers/net/e1000e/e1000_manage.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22-10/drivers/net/e1000e/e1000_manage.h 2009-06-24 00:32:20.000000000 +0200
+@@ -0,0 +1,82 @@
++/*******************************************************************************
++
++ Intel PRO/1000 Linux driver
++ Copyright(c) 1999 - 2009 Intel Corporation.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms and conditions of the GNU General Public License,
++ version 2, as published by the Free Software Foundation.
++
++ This program is distributed in the hope it will be useful, but WITHOUT
++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ You should have received a copy of the GNU General Public License along with
++ this program; if not, write to the Free Software Foundation, Inc.,
++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++
++ The full GNU General Public License is included in this distribution in
++ the file called "COPYING".
++
++ Contact Information:
++ Linux NICS <linux.nics@intel.com>
++ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++
++*******************************************************************************/
++
++#ifndef _E1000_MANAGE_H_
++#define _E1000_MANAGE_H_
++
++bool e1000_check_mng_mode_generic(struct e1000_hw *hw);
++bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw);
++s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw);
++s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
++ u16 length, u16 offset, u8 *sum);
++s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
++ struct e1000_host_mng_command_header *hdr);
++s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw,
++ u8 *buffer, u16 length);
++bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw);
++
++enum e1000_mng_mode {
++ e1000_mng_mode_none = 0,
++ e1000_mng_mode_asf,
++ e1000_mng_mode_pt,
++ e1000_mng_mode_ipmi,
++ e1000_mng_mode_host_if_only