/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2007 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 <linux/pci.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include "ixgbe_common.h"
#include "ixgbe_phy.h"
static s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw);
static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw);
static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw);
static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw);
static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw);
static s32 ixgbe_clear_vfta(struct ixgbe_hw *hw);
static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw);
static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr);
/**
* ixgbe_start_hw - Prepare hardware for TX/RX
* @hw: pointer to hardware structure
*
* Starts the hardware by filling the bus info structure and media type, clears
* all on chip counters, initializes receive address registers, multicast
* table, VLAN filter table, calls routine to set up link and flow control
* settings, and leaves transmit and receive units disabled and uninitialized
**/
s32 ixgbe_start_hw(struct ixgbe_hw *hw)
{
u32 ctrl_ext;
/* Set the media type */
hw->phy.media_type = hw->mac.ops.get_media_type(hw);
/* Identify the PHY */
ixgbe_identify_phy(hw);
/*
* Store MAC address from RAR0, clear receive address registers, and
* clear the multicast table
*/
ixgbe_init_rx_addrs(hw);
/* Clear the VLAN filter table */
ixgbe_clear_vfta(hw);
/* Set up link */
hw->mac.ops.setup_link(hw);
/* Clear statistics registers */
ixgbe_clear_hw_cntrs(hw);
/* Set No Snoop Disable */
ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS;
IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
IXGBE_WRITE_FLUSH(hw);
/* Clear adapter stopped flag */
hw->adapter_stopped = false;
return 0;
}
/**
* ixgbe_init_hw - Generic hardware initialization
* @hw: pointer to hardware structure
*
* Initialize the hardware by reseting the hardware, filling the bus info
* structure and media type, clears all on chip counters, initializes receive
* address registers, multicast table, VLAN filter table, calls routine to set
* up link and flow control settings, and leaves transmit and receive units
* disabled and uninitialized
**/
s32 ixgbe_init_hw(struct ixgbe_hw *hw)
{
/* Reset the hardware */
hw->mac.ops.reset(hw);
/* Start the HW */
ixgbe_start_hw(hw);
return 0;
}
/**
* ixgbe_clear_hw_cntrs - Generic clear hardware counters
* @hw: pointer to hardware structure
*
* Clears all hardware statistics counters by reading them from the hardware
* Statistics counters are clear on read.
**/
static s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw)
{
u16 i = 0;
IXGBE_READ_REG(hw, IXGBE_CRCERRS);
IXGBE_READ_REG(hw, IXGBE_ILLERRC);
IXGBE_READ_REG(hw, IXGBE_ERRBC);
IXGBE_READ_REG(hw, IXGBE_MSPDC);
for (i = 0; i < 8; i++)
IXGBE_READ_REG(hw, IXGBE_MPC(i));
IXGBE_READ_REG(hw, IXGBE_MLFC);
IXGBE_READ_REG(hw, IXGBE_MRFC);
IXGBE_READ_REG(hw, IXGBE_RLEC);
IXGBE_READ_REG(hw, IXGBE_LXONTXC);
IXGBE_READ_REG(hw, IXGBE_LXONRXC);
IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
for (i =