mirror of
https://github.com/xcat2/xNBA.git
synced 2026-05-11 17:04:10 +00:00
[e1000] Update e1000 driver
This commit replaces the current gPXE e1000 driver with one ported
from Intel source code available at
http://sourceforge.net/projects/e1000/
which is upstream source for the Linux kernel e1000 drivers, and
should support most if not all PCI e1000 variants.
Signed-off-by: Marty Connor <mdc@etherboot.org>
This commit is contained in:
+6
-1160
File diff suppressed because it is too large
Load Diff
+143
-123
@@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2006 Intel Corporation.
|
||||
Copyright(c) 1999 - 2008 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,
|
||||
@@ -33,19 +33,7 @@ FILE_LICENCE ( GPL2_ONLY );
|
||||
#ifndef _E1000_H_
|
||||
#define _E1000_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <gpxe/io.h>
|
||||
#include <errno.h>
|
||||
#include <byteswap.h>
|
||||
#include <gpxe/pci.h>
|
||||
#include <gpxe/malloc.h>
|
||||
#include <gpxe/if_ether.h>
|
||||
#include <gpxe/ethernet.h>
|
||||
#include <gpxe/iobuf.h>
|
||||
#include <gpxe/netdevice.h>
|
||||
#include "e1000_api.h"
|
||||
|
||||
#define BAR_0 0
|
||||
#define BAR_1 1
|
||||
@@ -53,11 +41,32 @@ FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
struct e1000_adapter;
|
||||
|
||||
#include "e1000_hw.h"
|
||||
/* TX/RX descriptor defines */
|
||||
#define E1000_DEFAULT_TXD 256
|
||||
#define E1000_MAX_TXD 256
|
||||
#define E1000_MIN_TXD 80
|
||||
#define E1000_MAX_82544_TXD 4096
|
||||
|
||||
#define E1000_DEFAULT_TXD_PWR 12
|
||||
#define E1000_MAX_TXD_PWR 12
|
||||
#define E1000_MIN_TXD_PWR 7
|
||||
|
||||
#define E1000_DEFAULT_RXD 256
|
||||
#define E1000_MAX_RXD 256
|
||||
|
||||
#define E1000_MIN_RXD 80
|
||||
#define E1000_MAX_82544_RXD 4096
|
||||
|
||||
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_128 128
|
||||
#define E1000_RXBUFFER_256 256
|
||||
#define E1000_RXBUFFER_512 512
|
||||
#define E1000_RXBUFFER_1024 1024
|
||||
#define E1000_RXBUFFER_2048 2048
|
||||
@@ -74,15 +83,11 @@ struct e1000_adapter;
|
||||
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||
|
||||
/* Flow Control Watermarks */
|
||||
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||
/* Early Receive defines */
|
||||
#define E1000_ERT_2048 0x100
|
||||
|
||||
#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define E1000_TX_QUEUE_WAKE 16
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
@@ -90,26 +95,31 @@ struct e1000_adapter;
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define E1000_EEPROM_82544_APM 0x0004
|
||||
#define E1000_EEPROM_ICH8_APME 0x0004
|
||||
#define E1000_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef E1000_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer */
|
||||
struct e1000_buffer {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
unsigned long time_stamp;
|
||||
uint16_t length;
|
||||
uint16_t next_to_watch;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
};
|
||||
|
||||
struct e1000_rx_buffer {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
struct page *page;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct e1000_tx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
@@ -121,14 +131,27 @@ struct e1000_tx_ring {
|
||||
/* array of buffer information structs */
|
||||
struct e1000_buffer *buffer_info;
|
||||
|
||||
uint16_t tdh;
|
||||
uint16_t tdt;
|
||||
boolean_t last_tx_tso;
|
||||
spinlock_t tx_lock;
|
||||
u16 tdh;
|
||||
u16 tdt;
|
||||
|
||||
/* TXDdescriptor index increment to be used when advancing
|
||||
* to the next descriptor. This is normally one, but on some
|
||||
* architectures, but on some architectures there are cache
|
||||
* coherency issues that require only the first descriptor in
|
||||
* cache line can be used.
|
||||
*/
|
||||
unsigned int step;
|
||||
|
||||
bool last_tx_tso;
|
||||
};
|
||||
|
||||
struct e1000_rx_ring {
|
||||
struct e1000_adapter *adapter; /* back link */
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
@@ -138,24 +161,28 @@ struct e1000_rx_ring {
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_buffer *buffer_info;
|
||||
/* arrays of page information for packet split */
|
||||
struct e1000_ps_page *ps_page;
|
||||
struct e1000_ps_page_dma *ps_page_dma;
|
||||
struct e1000_rx_buffer *buffer_info;
|
||||
struct sk_buff *rx_skb_top;
|
||||
|
||||
/* cpu for rx queue */
|
||||
int cpu;
|
||||
|
||||
uint16_t rdh;
|
||||
uint16_t rdt;
|
||||
u16 rdh;
|
||||
u16 rdt;
|
||||
};
|
||||
|
||||
|
||||
#define E1000_TX_DESC_INC(R,index) \
|
||||
{index += (R)->step; if (index == (R)->count) index = 0; }
|
||||
|
||||
#define E1000_TX_DESC_DEC(R,index) \
|
||||
{ if (index == 0) index = (R)->count - (R)->step; \
|
||||
else index -= (R)->step; }
|
||||
|
||||
#define E1000_DESC_UNUSED(R) \
|
||||
((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
|
||||
(R)->next_to_clean - (R)->next_to_use - 1)
|
||||
|
||||
#define E1000_RX_DESC_PS(R, i) \
|
||||
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
|
||||
#define E1000_RX_DESC_EXT(R, i) \
|
||||
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||
@@ -166,70 +193,63 @@ struct e1000_rx_ring {
|
||||
/* board specific private data structure */
|
||||
|
||||
struct e1000_adapter {
|
||||
struct vlan_group *vlgrp;
|
||||
uint16_t mng_vlan_id;
|
||||
uint32_t bd_number;
|
||||
uint32_t rx_buffer_len;
|
||||
uint32_t wol;
|
||||
uint32_t smartspeed;
|
||||
uint32_t en_mng_pt;
|
||||
uint16_t link_speed;
|
||||
uint16_t link_duplex;
|
||||
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 wol;
|
||||
u32 smartspeed;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
spinlock_t stats_lock;
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
/* Interrupt Throttle Rate */
|
||||
uint32_t itr;
|
||||
uint32_t itr_setting;
|
||||
uint16_t tx_itr;
|
||||
uint16_t rx_itr;
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
uint8_t fc_autoneg;
|
||||
|
||||
unsigned long led_status;
|
||||
bool fc_autoneg;
|
||||
|
||||
/* TX */
|
||||
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||
struct e1000_tx_ring *tx_ring;
|
||||
unsigned int restart_queue;
|
||||
unsigned long tx_queue_len;
|
||||
uint32_t txd_cmd;
|
||||
uint32_t tx_int_delay;
|
||||
uint32_t tx_abs_int_delay;
|
||||
uint32_t gotcl;
|
||||
uint64_t gotcl_old;
|
||||
uint64_t tpt_old;
|
||||
uint64_t colc_old;
|
||||
uint32_t tx_timeout_count;
|
||||
uint32_t tx_fifo_head;
|
||||
uint32_t tx_head_addr;
|
||||
uint32_t tx_fifo_size;
|
||||
uint8_t tx_timeout_factor;
|
||||
boolean_t pcix_82544;
|
||||
boolean_t detect_tx_hung;
|
||||
u32 txd_cmd;
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
u32 gotc;
|
||||
u64 gotc_old;
|
||||
u64 tpt_old;
|
||||
u64 colc_old;
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u8 tx_timeout_factor;
|
||||
bool pcix_82544;
|
||||
bool detect_tx_hung;
|
||||
|
||||
/* RX */
|
||||
boolean_t (*clean_rx) (struct e1000_adapter *adapter,
|
||||
bool (*clean_rx) (struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring);
|
||||
void (*alloc_rx_buf) (struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int cleaned_count);
|
||||
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||
int num_tx_queues;
|
||||
int num_rx_queues;
|
||||
struct e1000_rx_ring *rx_ring;
|
||||
|
||||
uint64_t hw_csum_err;
|
||||
uint64_t hw_csum_good;
|
||||
uint64_t rx_hdr_split;
|
||||
uint32_t alloc_rx_buff_failed;
|
||||
uint32_t rx_int_delay;
|
||||
uint32_t rx_abs_int_delay;
|
||||
boolean_t rx_csum;
|
||||
unsigned int rx_ps_pages;
|
||||
uint32_t gorcl;
|
||||
uint64_t gorcl_old;
|
||||
uint16_t rx_ps_bsize0;
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
bool rx_csum;
|
||||
u32 gorc;
|
||||
u64 gorc_old;
|
||||
u32 max_frame_size;
|
||||
u32 min_frame_size;
|
||||
|
||||
|
||||
/* OS defined structs */
|
||||
@@ -243,20 +263,19 @@ struct e1000_adapter {
|
||||
struct e1000_phy_info phy_info;
|
||||
struct e1000_phy_stats phy_stats;
|
||||
|
||||
uint32_t test_icr;
|
||||
struct e1000_tx_ring test_tx_ring;
|
||||
struct e1000_rx_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
boolean_t have_msi;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
boolean_t tso_force;
|
||||
boolean_t smart_power_down; /* phy smart power down */
|
||||
boolean_t quad_port_a;
|
||||
unsigned long flags;
|
||||
uint32_t eeprom_wol;
|
||||
|
||||
unsigned long state;
|
||||
u32 eeprom_wol;
|
||||
|
||||
u32 *config_space;
|
||||
|
||||
/* hardware capability, feature, and workaround flags */
|
||||
unsigned int flags;
|
||||
|
||||
/* upper limit parameter for tx desc size */
|
||||
u32 tx_desc_pwr;
|
||||
|
||||
#define NUM_TX_DESC 8
|
||||
#define NUM_RX_DESC 8
|
||||
|
||||
@@ -265,42 +284,43 @@ struct e1000_adapter {
|
||||
|
||||
struct e1000_tx_desc *tx_base;
|
||||
struct e1000_rx_desc *rx_base;
|
||||
|
||||
|
||||
uint32_t tx_ring_size;
|
||||
uint32_t rx_ring_size;
|
||||
|
||||
uint32_t tx_head;
|
||||
uint32_t tx_tail;
|
||||
uint32_t tx_fill_ctr;
|
||||
|
||||
|
||||
uint32_t rx_curr;
|
||||
|
||||
uint32_t ioaddr;
|
||||
uint32_t irqno;
|
||||
|
||||
};
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
__E1000_DOWN
|
||||
};
|
||||
#define E1000_FLAG_HAS_SMBUS (1 << 0)
|
||||
#define E1000_FLAG_HAS_INTR_MODERATION (1 << 4)
|
||||
#define E1000_FLAG_BAD_TX_CARRIER_STATS_FD (1 << 6)
|
||||
#define E1000_FLAG_QUAD_PORT_A (1 << 8)
|
||||
#define E1000_FLAG_SMART_POWER_DOWN (1 << 9)
|
||||
|
||||
#define E1000_MNG2HOST_PORT_623 (1 << 5)
|
||||
#define E1000_MNG2HOST_PORT_664 (1 << 6)
|
||||
extern char e1000_driver_name[];
|
||||
extern const char e1000_driver_version[];
|
||||
|
||||
#define E1000_ERT_2048 0x100
|
||||
extern void e1000_power_up_phy(struct e1000_hw *hw);
|
||||
|
||||
#define IORESOURCE_IO 0x00000100
|
||||
#define IORESOURCE_MEM 0x00000200
|
||||
#define IORESOURCE_PREFETCH 0x00001000
|
||||
extern void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||
extern void e1000_check_options(struct e1000_adapter *adapter);
|
||||
|
||||
extern int e1000_up(struct e1000_adapter *adapter);
|
||||
extern void e1000_down(struct e1000_adapter *adapter);
|
||||
extern void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||
extern void e1000_reset(struct e1000_adapter *adapter);
|
||||
extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
|
||||
extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||
extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_update_stats(struct e1000_adapter *adapter);
|
||||
|
||||
#endif /* _E1000_H_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* c-indent-level: 8
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,754 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/*
|
||||
* 82540EM Gigabit Ethernet Controller
|
||||
* 82540EP Gigabit Ethernet Controller
|
||||
* 82545EM Gigabit Ethernet Controller (Copper)
|
||||
* 82545EM Gigabit Ethernet Controller (Fiber)
|
||||
* 82545GM Gigabit Ethernet Controller
|
||||
* 82546EB Gigabit Ethernet Controller (Copper)
|
||||
* 82546EB Gigabit Ethernet Controller (Fiber)
|
||||
* 82546GB Gigabit Ethernet Controller
|
||||
*/
|
||||
|
||||
#include "e1000_api.h"
|
||||
|
||||
static s32 e1000_init_phy_params_82540(struct e1000_hw *hw);
|
||||
static s32 e1000_init_nvm_params_82540(struct e1000_hw *hw);
|
||||
static s32 e1000_init_mac_params_82540(struct e1000_hw *hw);
|
||||
static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw);
|
||||
static void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw);
|
||||
static s32 e1000_init_hw_82540(struct e1000_hw *hw);
|
||||
static s32 e1000_reset_hw_82540(struct e1000_hw *hw);
|
||||
static s32 e1000_set_phy_mode_82540(struct e1000_hw *hw);
|
||||
static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw);
|
||||
static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw);
|
||||
static s32 e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw);
|
||||
static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw);
|
||||
static s32 e1000_read_mac_addr_82540(struct e1000_hw *hw);
|
||||
|
||||
/**
|
||||
* e1000_init_phy_params_82540 - Init PHY func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
static s32 e1000_init_phy_params_82540(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_phy_info *phy = &hw->phy;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
|
||||
phy->addr = 1;
|
||||
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
|
||||
phy->reset_delay_us = 10000;
|
||||
phy->type = e1000_phy_m88;
|
||||
|
||||
/* Function Pointers */
|
||||
phy->ops.check_polarity = e1000_check_polarity_m88;
|
||||
phy->ops.commit = e1000_phy_sw_reset_generic;
|
||||
#if 0
|
||||
phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
|
||||
#endif
|
||||
#if 0
|
||||
phy->ops.get_cable_length = e1000_get_cable_length_m88;
|
||||
#endif
|
||||
phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
|
||||
phy->ops.read_reg = e1000_read_phy_reg_m88;
|
||||
phy->ops.reset = e1000_phy_hw_reset_generic;
|
||||
phy->ops.write_reg = e1000_write_phy_reg_m88;
|
||||
phy->ops.get_info = e1000_get_phy_info_m88;
|
||||
phy->ops.power_up = e1000_power_up_phy_copper;
|
||||
phy->ops.power_down = e1000_power_down_phy_copper_82540;
|
||||
|
||||
ret_val = e1000_get_phy_id(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
/* Verify phy id */
|
||||
switch (hw->mac.type) {
|
||||
case e1000_82540:
|
||||
case e1000_82545:
|
||||
case e1000_82545_rev_3:
|
||||
case e1000_82546:
|
||||
case e1000_82546_rev_3:
|
||||
if (phy->id == M88E1011_I_PHY_ID)
|
||||
break;
|
||||
/* Fall Through */
|
||||
default:
|
||||
ret_val = -E1000_ERR_PHY;
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_nvm_params_82540 - Init NVM func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
static s32 e1000_init_nvm_params_82540(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
|
||||
|
||||
DEBUGFUNC("e1000_init_nvm_params_82540");
|
||||
|
||||
nvm->type = e1000_nvm_eeprom_microwire;
|
||||
nvm->delay_usec = 50;
|
||||
nvm->opcode_bits = 3;
|
||||
switch (nvm->override) {
|
||||
case e1000_nvm_override_microwire_large:
|
||||
nvm->address_bits = 8;
|
||||
nvm->word_size = 256;
|
||||
break;
|
||||
case e1000_nvm_override_microwire_small:
|
||||
nvm->address_bits = 6;
|
||||
nvm->word_size = 64;
|
||||
break;
|
||||
default:
|
||||
nvm->address_bits = eecd & E1000_EECD_SIZE ? 8 : 6;
|
||||
nvm->word_size = eecd & E1000_EECD_SIZE ? 256 : 64;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Function Pointers */
|
||||
nvm->ops.acquire = e1000_acquire_nvm_generic;
|
||||
nvm->ops.read = e1000_read_nvm_microwire;
|
||||
nvm->ops.release = e1000_release_nvm_generic;
|
||||
nvm->ops.update = e1000_update_nvm_checksum_generic;
|
||||
nvm->ops.valid_led_default = e1000_valid_led_default_generic;
|
||||
nvm->ops.validate = e1000_validate_nvm_checksum_generic;
|
||||
nvm->ops.write = e1000_write_nvm_microwire;
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_mac_params_82540 - Init MAC func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
static s32 e1000_init_mac_params_82540(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mac_info *mac = &hw->mac;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
|
||||
DEBUGFUNC("e1000_init_mac_params_82540");
|
||||
|
||||
/* Set media type */
|
||||
switch (hw->device_id) {
|
||||
case E1000_DEV_ID_82545EM_FIBER:
|
||||
case E1000_DEV_ID_82545GM_FIBER:
|
||||
case E1000_DEV_ID_82546EB_FIBER:
|
||||
case E1000_DEV_ID_82546GB_FIBER:
|
||||
hw->phy.media_type = e1000_media_type_fiber;
|
||||
break;
|
||||
case E1000_DEV_ID_82545GM_SERDES:
|
||||
case E1000_DEV_ID_82546GB_SERDES:
|
||||
hw->phy.media_type = e1000_media_type_internal_serdes;
|
||||
break;
|
||||
default:
|
||||
hw->phy.media_type = e1000_media_type_copper;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set mta register count */
|
||||
mac->mta_reg_count = 128;
|
||||
/* Set rar entry count */
|
||||
mac->rar_entry_count = E1000_RAR_ENTRIES;
|
||||
|
||||
/* Function pointers */
|
||||
|
||||
/* bus type/speed/width */
|
||||
mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
|
||||
/* function id */
|
||||
mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci;
|
||||
/* reset */
|
||||
mac->ops.reset_hw = e1000_reset_hw_82540;
|
||||
/* hw initialization */
|
||||
mac->ops.init_hw = e1000_init_hw_82540;
|
||||
/* link setup */
|
||||
mac->ops.setup_link = e1000_setup_link_generic;
|
||||
/* physical interface setup */
|
||||
mac->ops.setup_physical_interface =
|
||||
(hw->phy.media_type == e1000_media_type_copper)
|
||||
? e1000_setup_copper_link_82540
|
||||
: e1000_setup_fiber_serdes_link_82540;
|
||||
/* check for link */
|
||||
switch (hw->phy.media_type) {
|
||||
case e1000_media_type_copper:
|
||||
mac->ops.check_for_link = e1000_check_for_copper_link_generic;
|
||||
break;
|
||||
case e1000_media_type_fiber:
|
||||
mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
|
||||
break;
|
||||
case e1000_media_type_internal_serdes:
|
||||
mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
|
||||
break;
|
||||
default:
|
||||
ret_val = -E1000_ERR_CONFIG;
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
/* link info */
|
||||
mac->ops.get_link_up_info =
|
||||
(hw->phy.media_type == e1000_media_type_copper)
|
||||
? e1000_get_speed_and_duplex_copper_generic
|
||||
: e1000_get_speed_and_duplex_fiber_serdes_generic;
|
||||
/* multicast address update */
|
||||
mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
|
||||
/* writing VFTA */
|
||||
mac->ops.write_vfta = e1000_write_vfta_generic;
|
||||
/* clearing VFTA */
|
||||
mac->ops.clear_vfta = e1000_clear_vfta_generic;
|
||||
/* setting MTA */
|
||||
mac->ops.mta_set = e1000_mta_set_generic;
|
||||
/* read mac address */
|
||||
mac->ops.read_mac_addr = e1000_read_mac_addr_82540;
|
||||
/* ID LED init */
|
||||
mac->ops.id_led_init = e1000_id_led_init_generic;
|
||||
/* setup LED */
|
||||
mac->ops.setup_led = e1000_setup_led_generic;
|
||||
/* cleanup LED */
|
||||
mac->ops.cleanup_led = e1000_cleanup_led_generic;
|
||||
/* turn on/off LED */
|
||||
mac->ops.led_on = e1000_led_on_generic;
|
||||
mac->ops.led_off = e1000_led_off_generic;
|
||||
/* clear hardware counters */
|
||||
mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82540;
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_function_pointers_82540 - Init func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Called to initialize all function pointers and parameters.
|
||||
**/
|
||||
void e1000_init_function_pointers_82540(struct e1000_hw *hw)
|
||||
{
|
||||
DEBUGFUNC("e1000_init_function_pointers_82540");
|
||||
|
||||
hw->mac.ops.init_params = e1000_init_mac_params_82540;
|
||||
hw->nvm.ops.init_params = e1000_init_nvm_params_82540;
|
||||
hw->phy.ops.init_params = e1000_init_phy_params_82540;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_reset_hw_82540 - Reset hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This resets the hardware into a known state.
|
||||
**/
|
||||
static s32 e1000_reset_hw_82540(struct e1000_hw *hw)
|
||||
{
|
||||
u32 ctrl, icr, manc;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
|
||||
DEBUGFUNC("e1000_reset_hw_82540");
|
||||
|
||||
DEBUGOUT("Masking off all interrupts\n");
|
||||
E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_RCTL, 0);
|
||||
E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
|
||||
/*
|
||||
* Delay to allow any outstanding PCI transactions to complete
|
||||
* before resetting the device.
|
||||
*/
|
||||
msec_delay(10);
|
||||
|
||||
ctrl = E1000_READ_REG(hw, E1000_CTRL);
|
||||
|
||||
DEBUGOUT("Issuing a global reset to 82540/82545/82546 MAC\n");
|
||||
switch (hw->mac.type) {
|
||||
case e1000_82545_rev_3:
|
||||
case e1000_82546_rev_3:
|
||||
E1000_WRITE_REG(hw, E1000_CTRL_DUP, ctrl | E1000_CTRL_RST);
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* These controllers can't ack the 64-bit write when
|
||||
* issuing the reset, so we use IO-mapping as a
|
||||
* workaround to issue the reset.
|
||||
*/
|
||||
E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wait for EEPROM reload */
|
||||
msec_delay(5);
|
||||
|
||||
/* Disable HW ARPs on ASF enabled adapters */
|
||||
manc = E1000_READ_REG(hw, E1000_MANC);
|
||||
manc &= ~E1000_MANC_ARP_EN;
|
||||
E1000_WRITE_REG(hw, E1000_MANC, manc);
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
|
||||
icr = E1000_READ_REG(hw, E1000_ICR);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_hw_82540 - Initialize hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This inits the hardware readying it for operation.
|
||||
**/
|
||||
static s32 e1000_init_hw_82540(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mac_info *mac = &hw->mac;
|
||||
u32 txdctl, ctrl_ext;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u16 i;
|
||||
|
||||
DEBUGFUNC("e1000_init_hw_82540");
|
||||
|
||||
/* Initialize identification LED */
|
||||
ret_val = mac->ops.id_led_init(hw);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("Error initializing identification LED\n");
|
||||
/* This is not fatal and we should not stop init due to this */
|
||||
}
|
||||
|
||||
/* Disabling VLAN filtering */
|
||||
DEBUGOUT("Initializing the IEEE VLAN\n");
|
||||
if (mac->type < e1000_82545_rev_3)
|
||||
E1000_WRITE_REG(hw, E1000_VET, 0);
|
||||
|
||||
mac->ops.clear_vfta(hw);
|
||||
|
||||
/* Setup the receive address. */
|
||||
e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
|
||||
|
||||
/* Zero out the Multicast HASH table */
|
||||
DEBUGOUT("Zeroing the MTA\n");
|
||||
for (i = 0; i < mac->mta_reg_count; i++) {
|
||||
E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
|
||||
/*
|
||||
* Avoid back to back register writes by adding the register
|
||||
* read (flush). This is to protect against some strange
|
||||
* bridge configurations that may issue Memory Write Block
|
||||
* (MWB) to our register space. The *_rev_3 hardware at
|
||||
* least doesn't respond correctly to every other dword in an
|
||||
* MWB to our register space.
|
||||
*/
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
}
|
||||
|
||||
if (mac->type < e1000_82545_rev_3)
|
||||
e1000_pcix_mmrbc_workaround_generic(hw);
|
||||
|
||||
/* Setup link and flow control */
|
||||
ret_val = mac->ops.setup_link(hw);
|
||||
|
||||
txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
|
||||
txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
|
||||
E1000_TXDCTL_FULL_TX_DESC_WB;
|
||||
E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
|
||||
|
||||
/*
|
||||
* 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_82540(hw);
|
||||
|
||||
if ((hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER) ||
|
||||
(hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3)) {
|
||||
ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
|
||||
/*
|
||||
* Relaxed ordering must be disabled to avoid a parity
|
||||
* error crash in a PCI slot.
|
||||
*/
|
||||
ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
|
||||
E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_setup_copper_link_82540 - Configure copper link settings
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Calls the appropriate function to configure the link for auto-neg or forced
|
||||
* speed and duplex. Then we check for link, once link is established calls
|
||||
* to configure collision distance and flow control are called. If link is
|
||||
* not established, we return -E1000_ERR_PHY (-2).
|
||||
**/
|
||||
static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw)
|
||||
{
|
||||
u32 ctrl;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u16 data;
|
||||
|
||||
DEBUGFUNC("e1000_setup_copper_link_82540");
|
||||
|
||||
ctrl = E1000_READ_REG(hw, E1000_CTRL);
|
||||
ctrl |= E1000_CTRL_SLU;
|
||||
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
|
||||
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
|
||||
|
||||
ret_val = e1000_set_phy_mode_82540(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
if (hw->mac.type == e1000_82545_rev_3 ||
|
||||
hw->mac.type == e1000_82546_rev_3) {
|
||||
ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &data);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
data |= 0x00000008;
|
||||
ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, data);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = e1000_copper_link_setup_m88(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
ret_val = e1000_setup_copper_link_generic(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_setup_fiber_serdes_link_82540 - Setup link for fiber/serdes
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Set the output amplitude to the value in the EEPROM and adjust the VCO
|
||||
* speed to improve Bit Error Rate (BER) performance. Configures collision
|
||||
* distance and flow control for fiber and serdes links. Upon successful
|
||||
* setup, poll for link.
|
||||
**/
|
||||
static s32 e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mac_info *mac = &hw->mac;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
|
||||
DEBUGFUNC("e1000_setup_fiber_serdes_link_82540");
|
||||
|
||||
switch (mac->type) {
|
||||
case e1000_82545_rev_3:
|
||||
case e1000_82546_rev_3:
|
||||
if (hw->phy.media_type == e1000_media_type_internal_serdes) {
|
||||
/*
|
||||
* If we're on serdes media, adjust the output
|
||||
* amplitude to value set in the EEPROM.
|
||||
*/
|
||||
ret_val = e1000_adjust_serdes_amplitude_82540(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
}
|
||||
/* Adjust VCO speed to improve BER performance */
|
||||
ret_val = e1000_set_vco_speed_82540(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret_val = e1000_setup_fiber_serdes_link_generic(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_adjust_serdes_amplitude_82540 - Adjust amplitude based on EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Adjust the SERDES output amplitude based on the EEPROM settings.
|
||||
**/
|
||||
static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u16 nvm_data;
|
||||
|
||||
DEBUGFUNC("e1000_adjust_serdes_amplitude_82540");
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, NVM_SERDES_AMPLITUDE, 1, &nvm_data);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
if (nvm_data != NVM_RESERVED_WORD) {
|
||||
/* Adjust serdes output amplitude only. */
|
||||
nvm_data &= NVM_SERDES_AMPLITUDE_MASK;
|
||||
ret_val = hw->phy.ops.write_reg(hw,
|
||||
M88E1000_PHY_EXT_CTRL,
|
||||
nvm_data);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_set_vco_speed_82540 - Set VCO speed for better performance
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Set the VCO speed to improve Bit Error Rate (BER) performance.
|
||||
**/
|
||||
static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u16 default_page = 0;
|
||||
u16 phy_data;
|
||||
|
||||
DEBUGFUNC("e1000_set_vco_speed_82540");
|
||||
|
||||
/* Set PHY register 30, page 5, bit 8 to 0 */
|
||||
|
||||
ret_val = hw->phy.ops.read_reg(hw,
|
||||
M88E1000_PHY_PAGE_SELECT,
|
||||
&default_page);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
phy_data &= ~M88E1000_PHY_VCO_REG_BIT8;
|
||||
ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
/* Set PHY register 30, page 4, bit 11 to 1 */
|
||||
|
||||
ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
phy_data |= M88E1000_PHY_VCO_REG_BIT11;
|
||||
ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT,
|
||||
default_page);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_set_phy_mode_82540 - Set PHY to class A mode
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Sets the PHY to class A mode and assumes the following operations will
|
||||
* follow to enable the new class mode:
|
||||
* 1. Do a PHY soft reset.
|
||||
* 2. Restart auto-negotiation or force link.
|
||||
**/
|
||||
static s32 e1000_set_phy_mode_82540(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_phy_info *phy = &hw->phy;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u16 nvm_data;
|
||||
|
||||
DEBUGFUNC("e1000_set_phy_mode_82540");
|
||||
|
||||
if (hw->mac.type != e1000_82545_rev_3)
|
||||
goto out;
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, NVM_PHY_CLASS_WORD, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
ret_val = -E1000_ERR_PHY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((nvm_data != NVM_RESERVED_WORD) && (nvm_data & NVM_PHY_CLASS_A)) {
|
||||
ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT,
|
||||
0x000B);
|
||||
if (ret_val) {
|
||||
ret_val = -E1000_ERR_PHY;
|
||||
goto out;
|
||||
}
|
||||
ret_val = hw->phy.ops.write_reg(hw,
|
||||
M88E1000_PHY_GEN_CONTROL,
|
||||
0x8104);
|
||||
if (ret_val) {
|
||||
ret_val = -E1000_ERR_PHY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
phy->reset_disable = false;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_power_down_phy_copper_82540 - Remove link in case of 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_82540(struct e1000_hw *hw)
|
||||
{
|
||||
/* If the management interface is not enabled, then power down */
|
||||
if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN))
|
||||
e1000_power_down_phy_copper(hw);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_clear_hw_cntrs_82540 - Clear device specific hardware counters
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Clears the hardware counters by reading the counter registers.
|
||||
**/
|
||||
static void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw)
|
||||
{
|
||||
DEBUGFUNC("e1000_clear_hw_cntrs_82540");
|
||||
|
||||
e1000_clear_hw_cntrs_base_generic(hw);
|
||||
|
||||
#if 0
|
||||
E1000_READ_REG(hw, E1000_PRC64);
|
||||
E1000_READ_REG(hw, E1000_PRC127);
|
||||
E1000_READ_REG(hw, E1000_PRC255);
|
||||
E1000_READ_REG(hw, E1000_PRC511);
|
||||
E1000_READ_REG(hw, E1000_PRC1023);
|
||||
E1000_READ_REG(hw, E1000_PRC1522);
|
||||
E1000_READ_REG(hw, E1000_PTC64);
|
||||
E1000_READ_REG(hw, E1000_PTC127);
|
||||
E1000_READ_REG(hw, E1000_PTC255);
|
||||
E1000_READ_REG(hw, E1000_PTC511);
|
||||
E1000_READ_REG(hw, E1000_PTC1023);
|
||||
E1000_READ_REG(hw, E1000_PTC1522);
|
||||
|
||||
E1000_READ_REG(hw, E1000_ALGNERRC);
|
||||
E1000_READ_REG(hw, E1000_RXERRC);
|
||||
E1000_READ_REG(hw, E1000_TNCRS);
|
||||
E1000_READ_REG(hw, E1000_CEXTERR);
|
||||
E1000_READ_REG(hw, E1000_TSCTC);
|
||||
E1000_READ_REG(hw, E1000_TSCTFC);
|
||||
|
||||
E1000_READ_REG(hw, E1000_MGTPRC);
|
||||
E1000_READ_REG(hw, E1000_MGTPDC);
|
||||
E1000_READ_REG(hw, E1000_MGTPTC);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_read_mac_addr_82540 - Read device MAC address
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Reads the device MAC address from the EEPROM and stores the value.
|
||||
* Since devices with two ports use the same EEPROM, we increment the
|
||||
* last bit in the MAC address for the second port.
|
||||
*
|
||||
* This version is being used over generic because of customer issues
|
||||
* with VmWare and Virtual Box when using generic. It seems in
|
||||
* the emulated 82545, RAR[0] does NOT have a valid address after a
|
||||
* reset, this older method works and using this breaks nothing for
|
||||
* these legacy adapters.
|
||||
**/
|
||||
s32 e1000_read_mac_addr_82540(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u16 offset, nvm_data, i;
|
||||
|
||||
DEBUGFUNC("e1000_read_mac_addr");
|
||||
|
||||
for (i = 0; i < ETH_ADDR_LEN; i += 2) {
|
||||
offset = i >> 1;
|
||||
ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
|
||||
hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
|
||||
}
|
||||
|
||||
/* Flip last bit of mac address if we're on second port */
|
||||
if (hw->bus.func == E1000_FUNC_1)
|
||||
hw->mac.perm_addr[5] ^= 1;
|
||||
|
||||
for (i = 0; i < ETH_ADDR_LEN; i++)
|
||||
hw->mac.addr[i] = hw->mac.perm_addr[i];
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static struct pci_device_id e1000_82540_nics[] = {
|
||||
PCI_ROM(0x8086, 0x100E, "E1000_DEV_ID_82540EM", "E1000_DEV_ID_82540EM", e1000_82540),
|
||||
PCI_ROM(0x8086, 0x1015, "E1000_DEV_ID_82540EM_LOM", "E1000_DEV_ID_82540EM_LOM", e1000_82540),
|
||||
PCI_ROM(0x8086, 0x1016, "E1000_DEV_ID_82540EP_LOM", "E1000_DEV_ID_82540EP_LOM", e1000_82540),
|
||||
PCI_ROM(0x8086, 0x1017, "E1000_DEV_ID_82540EP", "E1000_DEV_ID_82540EP", e1000_82540),
|
||||
PCI_ROM(0x8086, 0x101E, "E1000_DEV_ID_82540EP_LP", "E1000_DEV_ID_82540EP_LP", e1000_82540),
|
||||
PCI_ROM(0x8086, 0x100F, "E1000_DEV_ID_82545EM_COPPER", "E1000_DEV_ID_82545EM_COPPER", e1000_82545),
|
||||
PCI_ROM(0x8086, 0x1011, "E1000_DEV_ID_82545EM_FIBER", "E1000_DEV_ID_82545EM_FIBER", e1000_82545),
|
||||
PCI_ROM(0x8086, 0x1026, "E1000_DEV_ID_82545GM_COPPER", "E1000_DEV_ID_82545GM_COPPER", e1000_82545_rev_3),
|
||||
PCI_ROM(0x8086, 0x1027, "E1000_DEV_ID_82545GM_FIBER", "E1000_DEV_ID_82545GM_FIBER", e1000_82545_rev_3),
|
||||
PCI_ROM(0x8086, 0x1028, "E1000_DEV_ID_82545GM_SERDES", "E1000_DEV_ID_82545GM_SERDES", e1000_82545_rev_3),
|
||||
PCI_ROM(0x8086, 0x1010, "E1000_DEV_ID_82546EB_COPPER", "E1000_DEV_ID_82546EB_COPPER", e1000_82546),
|
||||
PCI_ROM(0x8086, 0x1012, "E1000_DEV_ID_82546EB_FIBER", "E1000_DEV_ID_82546EB_FIBER", e1000_82546),
|
||||
PCI_ROM(0x8086, 0x101D, "E1000_DEV_ID_82546EB_QUAD_COPPER", "E1000_DEV_ID_82546EB_QUAD_COPPER", e1000_82546),
|
||||
PCI_ROM(0x8086, 0x1079, "E1000_DEV_ID_82546GB_COPPER", "E1000_DEV_ID_82546GB_COPPER", e1000_82546_rev_3),
|
||||
PCI_ROM(0x8086, 0x107A, "E1000_DEV_ID_82546GB_FIBER", "E1000_DEV_ID_82546GB_FIBER", e1000_82546_rev_3),
|
||||
PCI_ROM(0x8086, 0x107B, "E1000_DEV_ID_82546GB_SERDES", "E1000_DEV_ID_82546GB_SERDES", e1000_82546_rev_3),
|
||||
PCI_ROM(0x8086, 0x108A, "E1000_DEV_ID_82546GB_PCIE", "E1000_DEV_ID_82546GB_PCIE", e1000_82546_rev_3),
|
||||
PCI_ROM(0x8086, 0x1099, "E1000_DEV_ID_82546GB_QUAD_COPPER", "E1000_DEV_ID_82546GB_QUAD_COPPER", e1000_82546_rev_3),
|
||||
PCI_ROM(0x8086, 0x10B5, "E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3", "E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3", e1000_82546_rev_3),
|
||||
};
|
||||
|
||||
struct pci_driver e1000_82540_driver __pci_driver = {
|
||||
.ids = e1000_82540_nics,
|
||||
.id_count = (sizeof (e1000_82540_nics) / sizeof (e1000_82540_nics[0])),
|
||||
.probe = e1000_probe,
|
||||
.remove = e1000_remove,
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,86 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#ifndef _E1000_82541_H_
|
||||
#define _E1000_82541_H_
|
||||
|
||||
#define NVM_WORD_SIZE_BASE_SHIFT_82541 (NVM_WORD_SIZE_BASE_SHIFT + 1)
|
||||
|
||||
#define IGP01E1000_PHY_CHANNEL_NUM 4
|
||||
|
||||
#define IGP01E1000_PHY_AGC_A 0x1172
|
||||
#define IGP01E1000_PHY_AGC_B 0x1272
|
||||
#define IGP01E1000_PHY_AGC_C 0x1472
|
||||
#define IGP01E1000_PHY_AGC_D 0x1872
|
||||
|
||||
#define IGP01E1000_PHY_AGC_PARAM_A 0x1171
|
||||
#define IGP01E1000_PHY_AGC_PARAM_B 0x1271
|
||||
#define IGP01E1000_PHY_AGC_PARAM_C 0x1471
|
||||
#define IGP01E1000_PHY_AGC_PARAM_D 0x1871
|
||||
|
||||
#define IGP01E1000_PHY_EDAC_MU_INDEX 0xC000
|
||||
#define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS 0x8000
|
||||
|
||||
#define IGP01E1000_PHY_DSP_RESET 0x1F33
|
||||
|
||||
#define IGP01E1000_PHY_DSP_FFE 0x1F35
|
||||
#define IGP01E1000_PHY_DSP_FFE_CM_CP 0x0069
|
||||
#define IGP01E1000_PHY_DSP_FFE_DEFAULT 0x002A
|
||||
|
||||
#define IGP01E1000_IEEE_FORCE_GIG 0x0140
|
||||
#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300
|
||||
|
||||
#define IGP01E1000_AGC_LENGTH_SHIFT 7
|
||||
#define IGP01E1000_AGC_RANGE 10
|
||||
|
||||
#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20
|
||||
#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100
|
||||
|
||||
#define IGP01E1000_ANALOG_FUSE_STATUS 0x20D0
|
||||
#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x20D1
|
||||
#define IGP01E1000_ANALOG_FUSE_CONTROL 0x20DC
|
||||
#define IGP01E1000_ANALOG_FUSE_BYPASS 0x20DE
|
||||
|
||||
#define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED 0x0100
|
||||
#define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80
|
||||
#define IGP01E1000_ANALOG_FUSE_COARSE_MASK 0x0070
|
||||
#define IGP01E1000_ANALOG_FUSE_COARSE_THRESH 0x0040
|
||||
#define IGP01E1000_ANALOG_FUSE_COARSE_10 0x0010
|
||||
#define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080
|
||||
#define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500
|
||||
#define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000
|
||||
#define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL 0x0002
|
||||
|
||||
#define IGP01E1000_MSE_CHANNEL_D 0x000F
|
||||
#define IGP01E1000_MSE_CHANNEL_C 0x00F0
|
||||
#define IGP01E1000_MSE_CHANNEL_B 0x0F00
|
||||
#define IGP01E1000_MSE_CHANNEL_A 0xF000
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,571 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/*
|
||||
* 82542 Gigabit Ethernet Controller
|
||||
*/
|
||||
|
||||
#include "e1000_api.h"
|
||||
|
||||
static s32 e1000_init_phy_params_82542(struct e1000_hw *hw);
|
||||
static s32 e1000_init_nvm_params_82542(struct e1000_hw *hw);
|
||||
static s32 e1000_init_mac_params_82542(struct e1000_hw *hw);
|
||||
static s32 e1000_get_bus_info_82542(struct e1000_hw *hw);
|
||||
static s32 e1000_reset_hw_82542(struct e1000_hw *hw);
|
||||
static s32 e1000_init_hw_82542(struct e1000_hw *hw);
|
||||
static s32 e1000_setup_link_82542(struct e1000_hw *hw);
|
||||
static s32 e1000_led_on_82542(struct e1000_hw *hw);
|
||||
static s32 e1000_led_off_82542(struct e1000_hw *hw);
|
||||
static void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index);
|
||||
static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw);
|
||||
|
||||
/**
|
||||
* e1000_init_phy_params_82542 - Init PHY func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
static s32 e1000_init_phy_params_82542(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_phy_info *phy = &hw->phy;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
|
||||
DEBUGFUNC("e1000_init_phy_params_82542");
|
||||
|
||||
phy->type = e1000_phy_none;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_nvm_params_82542 - Init NVM func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
static s32 e1000_init_nvm_params_82542(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
|
||||
DEBUGFUNC("e1000_init_nvm_params_82542");
|
||||
|
||||
nvm->address_bits = 6;
|
||||
nvm->delay_usec = 50;
|
||||
nvm->opcode_bits = 3;
|
||||
nvm->type = e1000_nvm_eeprom_microwire;
|
||||
nvm->word_size = 64;
|
||||
|
||||
/* Function Pointers */
|
||||
nvm->ops.read = e1000_read_nvm_microwire;
|
||||
nvm->ops.release = e1000_stop_nvm;
|
||||
nvm->ops.write = e1000_write_nvm_microwire;
|
||||
nvm->ops.update = e1000_update_nvm_checksum_generic;
|
||||
nvm->ops.validate = e1000_validate_nvm_checksum_generic;
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_mac_params_82542 - Init MAC func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
static s32 e1000_init_mac_params_82542(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mac_info *mac = &hw->mac;
|
||||
|
||||
DEBUGFUNC("e1000_init_mac_params_82542");
|
||||
|
||||
/* Set media type */
|
||||
hw->phy.media_type = e1000_media_type_fiber;
|
||||
|
||||
/* Set mta register count */
|
||||
mac->mta_reg_count = 128;
|
||||
/* Set rar entry count */
|
||||
mac->rar_entry_count = E1000_RAR_ENTRIES;
|
||||
|
||||
/* Function pointers */
|
||||
|
||||
/* bus type/speed/width */
|
||||
mac->ops.get_bus_info = e1000_get_bus_info_82542;
|
||||
/* function id */
|
||||
mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci;
|
||||
/* reset */
|
||||
mac->ops.reset_hw = e1000_reset_hw_82542;
|
||||
/* hw initialization */
|
||||
mac->ops.init_hw = e1000_init_hw_82542;
|
||||
/* link setup */
|
||||
mac->ops.setup_link = e1000_setup_link_82542;
|
||||
/* phy/fiber/serdes setup */
|
||||
mac->ops.setup_physical_interface = e1000_setup_fiber_serdes_link_generic;
|
||||
/* check for link */
|
||||
mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
|
||||
/* multicast address update */
|
||||
mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
|
||||
/* writing VFTA */
|
||||
mac->ops.write_vfta = e1000_write_vfta_generic;
|
||||
/* clearing VFTA */
|
||||
mac->ops.clear_vfta = e1000_clear_vfta_generic;
|
||||
/* setting MTA */
|
||||
mac->ops.mta_set = e1000_mta_set_generic;
|
||||
/* set RAR */
|
||||
mac->ops.rar_set = e1000_rar_set_82542;
|
||||
/* turn on/off LED */
|
||||
mac->ops.led_on = e1000_led_on_82542;
|
||||
mac->ops.led_off = e1000_led_off_82542;
|
||||
/* clear hardware counters */
|
||||
mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82542;
|
||||
/* link info */
|
||||
mac->ops.get_link_up_info = e1000_get_speed_and_duplex_fiber_serdes_generic;
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_function_pointers_82542 - Init func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Called to initialize all function pointers and parameters.
|
||||
**/
|
||||
void e1000_init_function_pointers_82542(struct e1000_hw *hw)
|
||||
{
|
||||
DEBUGFUNC("e1000_init_function_pointers_82542");
|
||||
|
||||
hw->mac.ops.init_params = e1000_init_mac_params_82542;
|
||||
hw->nvm.ops.init_params = e1000_init_nvm_params_82542;
|
||||
hw->phy.ops.init_params = e1000_init_phy_params_82542;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_get_bus_info_82542 - Obtain bus information for adapter
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This will obtain information about the HW bus for which the
|
||||
* adapter is attached and stores it in the hw structure.
|
||||
**/
|
||||
static s32 e1000_get_bus_info_82542(struct e1000_hw *hw)
|
||||
{
|
||||
DEBUGFUNC("e1000_get_bus_info_82542");
|
||||
|
||||
hw->bus.type = e1000_bus_type_pci;
|
||||
hw->bus.speed = e1000_bus_speed_unknown;
|
||||
hw->bus.width = e1000_bus_width_unknown;
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_reset_hw_82542 - Reset hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This resets the hardware into a known state.
|
||||
**/
|
||||
static s32 e1000_reset_hw_82542(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_bus_info *bus = &hw->bus;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u32 ctrl, icr;
|
||||
|
||||
DEBUGFUNC("e1000_reset_hw_82542");
|
||||
|
||||
if (hw->revision_id == E1000_REVISION_2) {
|
||||
DEBUGOUT("Disabling MWI on 82542 rev 2\n");
|
||||
e1000_pci_clear_mwi(hw);
|
||||
}
|
||||
|
||||
DEBUGOUT("Masking off all interrupts\n");
|
||||
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_RCTL, 0);
|
||||
E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
|
||||
/*
|
||||
* Delay to allow any outstanding PCI transactions to complete before
|
||||
* resetting the device
|
||||
*/
|
||||
msec_delay(10);
|
||||
|
||||
ctrl = E1000_READ_REG(hw, E1000_CTRL);
|
||||
|
||||
DEBUGOUT("Issuing a global reset to 82542/82543 MAC\n");
|
||||
E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
|
||||
|
||||
hw->nvm.ops.reload(hw);
|
||||
msec_delay(2);
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
|
||||
icr = E1000_READ_REG(hw, E1000_ICR);
|
||||
|
||||
if (hw->revision_id == E1000_REVISION_2) {
|
||||
if (bus->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
|
||||
e1000_pci_set_mwi(hw);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_hw_82542 - Initialize hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This inits the hardware readying it for operation.
|
||||
**/
|
||||
static s32 e1000_init_hw_82542(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mac_info *mac = &hw->mac;
|
||||
struct e1000_dev_spec_82542 *dev_spec = &hw->dev_spec._82542;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u32 ctrl;
|
||||
u16 i;
|
||||
|
||||
DEBUGFUNC("e1000_init_hw_82542");
|
||||
|
||||
/* Disabling VLAN filtering */
|
||||
E1000_WRITE_REG(hw, E1000_VET, 0);
|
||||
mac->ops.clear_vfta(hw);
|
||||
|
||||
/* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
|
||||
if (hw->revision_id == E1000_REVISION_2) {
|
||||
DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
|
||||
e1000_pci_clear_mwi(hw);
|
||||
E1000_WRITE_REG(hw, E1000_RCTL, E1000_RCTL_RST);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
msec_delay(5);
|
||||
}
|
||||
|
||||
/* Setup the receive address. */
|
||||
e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
|
||||
|
||||
/* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
|
||||
if (hw->revision_id == E1000_REVISION_2) {
|
||||
E1000_WRITE_REG(hw, E1000_RCTL, 0);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
msec_delay(1);
|
||||
if (hw->bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
|
||||
e1000_pci_set_mwi(hw);
|
||||
}
|
||||
|
||||
/* Zero out the Multicast HASH table */
|
||||
DEBUGOUT("Zeroing the MTA\n");
|
||||
for (i = 0; i < mac->mta_reg_count; i++)
|
||||
E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
|
||||
|
||||
/*
|
||||
* Set the PCI priority bit correctly in the CTRL register. This
|
||||
* determines if the adapter gives priority to receives, or if it
|
||||
* gives equal priority to transmits and receives.
|
||||
*/
|
||||
if (dev_spec->dma_fairness) {
|
||||
ctrl = E1000_READ_REG(hw, E1000_CTRL);
|
||||
E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PRIOR);
|
||||
}
|
||||
|
||||
/* Setup link and flow control */
|
||||
ret_val = e1000_setup_link_82542(hw);
|
||||
|
||||
/*
|
||||
* Clear all of the statistics registers (clear on read). It is
|
||||
* important that we do this after we have tried to establish link
|
||||
* because the symbol error count will increment wildly if there
|
||||
* is no link.
|
||||
*/
|
||||
e1000_clear_hw_cntrs_82542(hw);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_setup_link_82542 - 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_82542(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mac_info *mac = &hw->mac;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
|
||||
DEBUGFUNC("e1000_setup_link_82542");
|
||||
|
||||
ret_val = e1000_set_default_fc_generic(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
hw->fc.requested_mode &= ~e1000_fc_tx_pause;
|
||||
|
||||
if (mac->report_tx_early == 1)
|
||||
hw->fc.requested_mode &= ~e1000_fc_rx_pause;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
DEBUGOUT1("After fix-ups FlowControl is now = %x\n",
|
||||
hw->fc.current_mode);
|
||||
|
||||
/* Call the necessary subroutine to configure the link. */
|
||||
ret_val = 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.
|
||||
*/
|
||||
DEBUGOUT("Initializing Flow Control address, type and timer regs\n");
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW);
|
||||
E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH);
|
||||
E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE);
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time);
|
||||
|
||||
ret_val = e1000_set_fc_watermarks_generic(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_led_on_82542 - Turn on SW controllable LED
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Turns the SW defined LED on.
|
||||
**/
|
||||
static s32 e1000_led_on_82542(struct e1000_hw *hw __unused)
|
||||
{
|
||||
#if 0
|
||||
u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
|
||||
|
||||
DEBUGFUNC("e1000_led_on_82542");
|
||||
|
||||
ctrl |= E1000_CTRL_SWDPIN0;
|
||||
ctrl |= E1000_CTRL_SWDPIO0;
|
||||
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
|
||||
|
||||
return E1000_SUCCESS;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_led_off_82542 - Turn off SW controllable LED
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Turns the SW defined LED off.
|
||||
**/
|
||||
static s32 e1000_led_off_82542(struct e1000_hw *hw __unused)
|
||||
{
|
||||
#if 0
|
||||
u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
|
||||
|
||||
DEBUGFUNC("e1000_led_off_82542");
|
||||
|
||||
ctrl &= ~E1000_CTRL_SWDPIN0;
|
||||
ctrl |= E1000_CTRL_SWDPIO0;
|
||||
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
|
||||
|
||||
return E1000_SUCCESS;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_rar_set_82542 - 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.
|
||||
**/
|
||||
static void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index)
|
||||
{
|
||||
u32 rar_low, rar_high;
|
||||
|
||||
DEBUGFUNC("e1000_rar_set_82542");
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low);
|
||||
E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_translate_register_82542 - Translate the proper register offset
|
||||
* @reg: e1000 register to be read
|
||||
*
|
||||
* Registers in 82542 are located in different offsets than other adapters
|
||||
* even though they function in the same manner. This function takes in
|
||||
* the name of the register to read and returns the correct offset for
|
||||
* 82542 silicon.
|
||||
**/
|
||||
u32 e1000_translate_register_82542(u32 reg)
|
||||
{
|
||||
/*
|
||||
* Some of the 82542 registers are located at different
|
||||
* offsets than they are in newer adapters.
|
||||
* Despite the difference in location, the registers
|
||||
* function in the same manner.
|
||||
*/
|
||||
switch (reg) {
|
||||
case E1000_RA:
|
||||
reg = 0x00040;
|
||||
break;
|
||||
case E1000_RDTR:
|
||||
reg = 0x00108;
|
||||
break;
|
||||
case E1000_RDBAL(0):
|
||||
reg = 0x00110;
|
||||
break;
|
||||
case E1000_RDBAH(0):
|
||||
reg = 0x00114;
|
||||
break;
|
||||
case E1000_RDLEN(0):
|
||||
reg = 0x00118;
|
||||
break;
|
||||
case E1000_RDH(0):
|
||||
reg = 0x00120;
|
||||
break;
|
||||
case E1000_RDT(0):
|
||||
reg = 0x00128;
|
||||
break;
|
||||
case E1000_RDBAL(1):
|
||||
reg = 0x00138;
|
||||
break;
|
||||
case E1000_RDBAH(1):
|
||||
reg = 0x0013C;
|
||||
break;
|
||||
case E1000_RDLEN(1):
|
||||
reg = 0x00140;
|
||||
break;
|
||||
case E1000_RDH(1):
|
||||
reg = 0x00148;
|
||||
break;
|
||||
case E1000_RDT(1):
|
||||
reg = 0x00150;
|
||||
break;
|
||||
case E1000_FCRTH:
|
||||
reg = 0x00160;
|
||||
break;
|
||||
case E1000_FCRTL:
|
||||
reg = 0x00168;
|
||||
break;
|
||||
case E1000_MTA:
|
||||
reg = 0x00200;
|
||||
break;
|
||||
case E1000_TDBAL(0):
|
||||
reg = 0x00420;
|
||||
break;
|
||||
case E1000_TDBAH(0):
|
||||
reg = 0x00424;
|
||||
break;
|
||||
case E1000_TDLEN(0):
|
||||
reg = 0x00428;
|
||||
break;
|
||||
case E1000_TDH(0):
|
||||
reg = 0x00430;
|
||||
break;
|
||||
case E1000_TDT(0):
|
||||
reg = 0x00438;
|
||||
break;
|
||||
case E1000_TIDV:
|
||||
reg = 0x00440;
|
||||
break;
|
||||
case E1000_VFTA:
|
||||
reg = 0x00600;
|
||||
break;
|
||||
case E1000_TDFH:
|
||||
reg = 0x08010;
|
||||
break;
|
||||
case E1000_TDFT:
|
||||
reg = 0x08018;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_clear_hw_cntrs_82542 - Clear device specific hardware counters
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Clears the hardware counters by reading the counter registers.
|
||||
**/
|
||||
static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw)
|
||||
{
|
||||
DEBUGFUNC("e1000_clear_hw_cntrs_82542");
|
||||
|
||||
e1000_clear_hw_cntrs_base_generic(hw);
|
||||
|
||||
#if 0
|
||||
E1000_READ_REG(hw, E1000_PRC64);
|
||||
E1000_READ_REG(hw, E1000_PRC127);
|
||||
E1000_READ_REG(hw, E1000_PRC255);
|
||||
E1000_READ_REG(hw, E1000_PRC511);
|
||||
E1000_READ_REG(hw, E1000_PRC1023);
|
||||
E1000_READ_REG(hw, E1000_PRC1522);
|
||||
E1000_READ_REG(hw, E1000_PTC64);
|
||||
E1000_READ_REG(hw, E1000_PTC127);
|
||||
E1000_READ_REG(hw, E1000_PTC255);
|
||||
E1000_READ_REG(hw, E1000_PTC511);
|
||||
E1000_READ_REG(hw, E1000_PTC1023);
|
||||
E1000_READ_REG(hw, E1000_PTC1522);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct pci_device_id e1000_82542_nics[] = {
|
||||
PCI_ROM(0x8086, 0x1000, "E1000_DEV_ID_82542", "E1000_DEV_ID_82542", e1000_82542),
|
||||
};
|
||||
|
||||
struct pci_driver e1000_82542_driver __pci_driver = {
|
||||
.ids = e1000_82542_nics,
|
||||
.id_count = (sizeof (e1000_82542_nics) / sizeof (e1000_82542_nics[0])),
|
||||
.probe = e1000_probe,
|
||||
.remove = e1000_remove,
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,45 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#ifndef _E1000_82543_H_
|
||||
#define _E1000_82543_H_
|
||||
|
||||
#define PHY_PREAMBLE 0xFFFFFFFF
|
||||
#define PHY_PREAMBLE_SIZE 32
|
||||
#define PHY_SOF 0x1
|
||||
#define PHY_OP_READ 0x2
|
||||
#define PHY_OP_WRITE 0x1
|
||||
#define PHY_TURNAROUND 0x2
|
||||
|
||||
#define TBI_COMPAT_ENABLED 0x1 /* Global "knob" for the workaround */
|
||||
/* If TBI_COMPAT_ENABLED, then this is the current state (on/off) */
|
||||
#define TBI_SBP_ENABLED 0x2
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,128 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#ifndef _E1000_API_H_
|
||||
#define _E1000_API_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <gpxe/io.h>
|
||||
#include <errno.h>
|
||||
#include <byteswap.h>
|
||||
#include <gpxe/pci.h>
|
||||
#include <gpxe/malloc.h>
|
||||
#include <gpxe/if_ether.h>
|
||||
#include <gpxe/ethernet.h>
|
||||
#include <gpxe/iobuf.h>
|
||||
#include <gpxe/netdevice.h>
|
||||
|
||||
#include "e1000_hw.h"
|
||||
|
||||
extern void e1000_init_function_pointers_82542(struct e1000_hw *hw) __attribute__((weak));
|
||||
extern void e1000_init_function_pointers_82543(struct e1000_hw *hw) __attribute__((weak));
|
||||
extern void e1000_init_function_pointers_82540(struct e1000_hw *hw) __attribute__((weak));
|
||||
extern void e1000_init_function_pointers_82541(struct e1000_hw *hw) __attribute__((weak));
|
||||
|
||||
s32 e1000_set_mac_type(struct e1000_hw *hw);
|
||||
s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device);
|
||||
s32 e1000_init_mac_params(struct e1000_hw *hw);
|
||||
s32 e1000_init_nvm_params(struct e1000_hw *hw);
|
||||
s32 e1000_init_phy_params(struct e1000_hw *hw);
|
||||
s32 e1000_get_bus_info(struct e1000_hw *hw);
|
||||
void e1000_clear_vfta(struct e1000_hw *hw);
|
||||
void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value);
|
||||
s32 e1000_force_mac_fc(struct e1000_hw *hw);
|
||||
s32 e1000_check_for_link(struct e1000_hw *hw);
|
||||
s32 e1000_reset_hw(struct e1000_hw *hw);
|
||||
s32 e1000_init_hw(struct e1000_hw *hw);
|
||||
s32 e1000_setup_link(struct e1000_hw *hw);
|
||||
s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed,
|
||||
u16 *duplex);
|
||||
s32 e1000_disable_pcie_master(struct e1000_hw *hw);
|
||||
void e1000_config_collision_dist(struct e1000_hw *hw);
|
||||
void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
|
||||
void e1000_mta_set(struct e1000_hw *hw, u32 hash_value);
|
||||
u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr);
|
||||
void e1000_update_mc_addr_list(struct e1000_hw *hw,
|
||||
u8 *mc_addr_list, u32 mc_addr_count);
|
||||
s32 e1000_setup_led(struct e1000_hw *hw);
|
||||
s32 e1000_cleanup_led(struct e1000_hw *hw);
|
||||
s32 e1000_check_reset_block(struct e1000_hw *hw);
|
||||
s32 e1000_blink_led(struct e1000_hw *hw);
|
||||
s32 e1000_led_on(struct e1000_hw *hw);
|
||||
s32 e1000_led_off(struct e1000_hw *hw);
|
||||
s32 e1000_id_led_init(struct e1000_hw *hw);
|
||||
void e1000_reset_adaptive(struct e1000_hw *hw);
|
||||
void e1000_update_adaptive(struct e1000_hw *hw);
|
||||
#if 0
|
||||
s32 e1000_get_cable_length(struct e1000_hw *hw);
|
||||
#endif
|
||||
s32 e1000_validate_mdi_setting(struct e1000_hw *hw);
|
||||
s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 e1000_get_phy_info(struct e1000_hw *hw);
|
||||
void e1000_release_phy(struct e1000_hw *hw);
|
||||
s32 e1000_acquire_phy(struct e1000_hw *hw);
|
||||
s32 e1000_phy_hw_reset(struct e1000_hw *hw);
|
||||
s32 e1000_phy_commit(struct e1000_hw *hw);
|
||||
void e1000_power_up_phy(struct e1000_hw *hw);
|
||||
void e1000_power_down_phy(struct e1000_hw *hw);
|
||||
s32 e1000_read_mac_addr(struct e1000_hw *hw);
|
||||
s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *part_num);
|
||||
void e1000_reload_nvm(struct e1000_hw *hw);
|
||||
s32 e1000_update_nvm_checksum(struct e1000_hw *hw);
|
||||
s32 e1000_validate_nvm_checksum(struct e1000_hw *hw);
|
||||
s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
|
||||
s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words,
|
||||
u16 *data);
|
||||
s32 e1000_wait_autoneg(struct e1000_hw *hw);
|
||||
s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
|
||||
s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
|
||||
bool e1000_check_mng_mode(struct e1000_hw *hw);
|
||||
bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
|
||||
s32 e1000_mng_enable_host_if(struct e1000_hw *hw);
|
||||
s32 e1000_mng_host_if_write(struct e1000_hw *hw,
|
||||
u8 *buffer, u16 length, u16 offset, u8 *sum);
|
||||
s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
|
||||
struct e1000_host_mng_command_header *hdr);
|
||||
s32 e1000_mng_write_dhcp_info(struct e1000_hw * hw,
|
||||
u8 *buffer, u16 length);
|
||||
u32 e1000_translate_register_82542(u32 reg) __attribute__((weak));
|
||||
|
||||
extern int e1000_probe(struct pci_device *pdev,
|
||||
const struct pci_device_id *id __unused);
|
||||
extern void e1000_remove(struct pci_device *pdev);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+632
-3335
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,94 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#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);
|
||||
void e1000_null_mac_generic(struct e1000_hw *hw);
|
||||
s32 e1000_null_ops_generic(struct e1000_hw *hw);
|
||||
s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d);
|
||||
bool e1000_null_mng_mode(struct e1000_hw *hw);
|
||||
void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a);
|
||||
void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b);
|
||||
void e1000_null_mta_set(struct e1000_hw *hw, u32 a);
|
||||
void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a);
|
||||
s32 e1000_blink_led_generic(struct e1000_hw *hw);
|
||||
s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw);
|
||||
s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw);
|
||||
s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw);
|
||||
s32 e1000_cleanup_led_generic(struct e1000_hw *hw);
|
||||
s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw);
|
||||
s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw);
|
||||
s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw);
|
||||
s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw);
|
||||
s32 e1000_force_mac_fc_generic(struct e1000_hw *hw);
|
||||
s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw);
|
||||
s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw);
|
||||
s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw);
|
||||
void e1000_set_lan_id_single_port(struct e1000_hw *hw);
|
||||
void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw);
|
||||
s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw);
|
||||
s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
|
||||
u16 *duplex);
|
||||
s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
|
||||
u16 *speed, u16 *duplex);
|
||||
s32 e1000_id_led_init_generic(struct e1000_hw *hw);
|
||||
s32 e1000_led_on_generic(struct e1000_hw *hw);
|
||||
s32 e1000_led_off_generic(struct e1000_hw *hw);
|
||||
void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
|
||||
u8 *mc_addr_list, u32 mc_addr_count);
|
||||
s32 e1000_set_default_fc_generic(struct e1000_hw *hw);
|
||||
s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw);
|
||||
s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw);
|
||||
s32 e1000_setup_led_generic(struct e1000_hw *hw);
|
||||
s32 e1000_setup_link_generic(struct e1000_hw *hw);
|
||||
|
||||
u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr);
|
||||
|
||||
void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw);
|
||||
void e1000_clear_vfta_generic(struct e1000_hw *hw);
|
||||
void e1000_config_collision_dist_generic(struct e1000_hw *hw);
|
||||
void e1000_init_rx_addrs_generic(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 e1000_put_hw_semaphore_generic(struct e1000_hw *hw);
|
||||
void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index);
|
||||
s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw);
|
||||
void e1000_reset_adaptive_generic(struct e1000_hw *hw);
|
||||
void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop);
|
||||
void e1000_update_adaptive_generic(struct e1000_hw *hw);
|
||||
void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,912 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 Intel Corporation.
|
||||
|
||||
Portions Copyright(c) 2010 Marty Connor <mdc@etherboot.org>
|
||||
Portions Copyright(c) 2010 Entity Cyber, Inc.
|
||||
|
||||
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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
#include "e1000.h"
|
||||
|
||||
/**
|
||||
* e1000_irq_disable - Disable interrupt generation
|
||||
*
|
||||
* @adapter: board private structure
|
||||
**/
|
||||
static void e1000_irq_disable ( struct e1000_adapter *adapter )
|
||||
{
|
||||
E1000_WRITE_REG ( &adapter->hw, E1000_IMC, ~0 );
|
||||
E1000_WRITE_FLUSH ( &adapter->hw );
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_irq_enable - Enable interrupt generation
|
||||
*
|
||||
* @adapter: board private structure
|
||||
**/
|
||||
static void e1000_irq_enable ( struct e1000_adapter *adapter )
|
||||
{
|
||||
E1000_WRITE_REG(&adapter->hw, E1000_IMS, IMS_ENABLE_MASK);
|
||||
E1000_WRITE_FLUSH(&adapter->hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_sw_init - Initialize general software structures (struct e1000_adapter)
|
||||
* @adapter: board private structure to initialize
|
||||
*
|
||||
* e1000_sw_init initializes the Adapter private data structure.
|
||||
* Fields are initialized based on PCI device information and
|
||||
* OS network device settings (MTU size).
|
||||
**/
|
||||
static int e1000_sw_init(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
struct pci_device *pdev = adapter->pdev;
|
||||
|
||||
/* PCI config space info */
|
||||
|
||||
hw->vendor_id = pdev->vendor;
|
||||
hw->device_id = pdev->device;
|
||||
|
||||
pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &hw->subsystem_vendor_id);
|
||||
pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &hw->subsystem_device_id);
|
||||
|
||||
pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
|
||||
|
||||
pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word);
|
||||
|
||||
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
|
||||
adapter->max_frame_size = MAXIMUM_ETHERNET_VLAN_SIZE +
|
||||
ETH_HLEN + ETH_FCS_LEN;
|
||||
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
|
||||
|
||||
hw->fc.requested_mode = e1000_fc_none;
|
||||
|
||||
/* Initialize the hardware-specific values */
|
||||
if (e1000_setup_init_funcs(hw, false)) {
|
||||
DBG ("Hardware Initialization Failure\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Explicitly disable IRQ since the NIC can be in any state. */
|
||||
e1000_irq_disable ( adapter );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
|
||||
{
|
||||
struct e1000_adapter *adapter = hw->back;
|
||||
uint16_t cap_offset;
|
||||
|
||||
#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
|
||||
cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
|
||||
if (!cap_offset)
|
||||
return -E1000_ERR_CONFIG;
|
||||
|
||||
pci_read_config_word(adapter->pdev, cap_offset + reg, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void e1000_pci_clear_mwi ( struct e1000_hw *hw )
|
||||
{
|
||||
struct e1000_adapter *adapter = hw->back;
|
||||
|
||||
pci_write_config_word ( adapter->pdev, PCI_COMMAND,
|
||||
hw->bus.pci_cmd_word & ~PCI_COMMAND_INVALIDATE );
|
||||
}
|
||||
|
||||
void e1000_pci_set_mwi ( struct e1000_hw *hw )
|
||||
{
|
||||
struct e1000_adapter *adapter = hw->back;
|
||||
|
||||
pci_write_config_word ( adapter->pdev, PCI_COMMAND,
|
||||
hw->bus.pci_cmd_word );
|
||||
}
|
||||
|
||||
void e1000_read_pci_cfg ( struct e1000_hw *hw, uint32_t reg, uint16_t *value )
|
||||
{
|
||||
struct e1000_adapter *adapter = hw->back;
|
||||
|
||||
pci_read_config_word ( adapter->pdev, reg, value );
|
||||
}
|
||||
|
||||
void e1000_write_pci_cfg ( struct e1000_hw *hw, uint32_t reg, uint16_t *value )
|
||||
{
|
||||
struct e1000_adapter *adapter = hw->back;
|
||||
|
||||
pci_write_config_word ( adapter->pdev, reg, *value );
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_manageability - disable interception of ARP packets
|
||||
*
|
||||
* @v adapter e1000 private structure
|
||||
**/
|
||||
static void e1000_init_manageability ( struct e1000_adapter *adapter )
|
||||
{
|
||||
if (adapter->en_mng_pt) {
|
||||
u32 manc = E1000_READ_REG(&adapter->hw, E1000_MANC);
|
||||
|
||||
/* disable hardware interception of ARP */
|
||||
manc &= ~(E1000_MANC_ARP_EN);
|
||||
|
||||
E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_setup_tx_resources - allocate Tx resources (Descriptors)
|
||||
*
|
||||
* @v adapter e1000 private structure
|
||||
*
|
||||
* @ret rc Returns 0 on success, negative on failure
|
||||
**/
|
||||
static int e1000_setup_tx_resources ( struct e1000_adapter *adapter )
|
||||
{
|
||||
DBG ( "e1000_setup_tx_resources\n" );
|
||||
|
||||
/* Allocate transmit descriptor ring memory.
|
||||
It must not cross a 64K boundary because of hardware errata #23
|
||||
so we use malloc_dma() requesting a 128 byte block that is
|
||||
128 byte aligned. This should guarantee that the memory
|
||||
allocated will not cross a 64K boundary, because 128 is an
|
||||
even multiple of 65536 ( 65536 / 128 == 512 ), so all possible
|
||||
allocations of 128 bytes on a 128 byte boundary will not
|
||||
cross 64K bytes.
|
||||
*/
|
||||
|
||||
adapter->tx_base =
|
||||
malloc_dma ( adapter->tx_ring_size, adapter->tx_ring_size );
|
||||
|
||||
if ( ! adapter->tx_base ) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset ( adapter->tx_base, 0, adapter->tx_ring_size );
|
||||
|
||||
DBG ( "adapter->tx_base = %#08lx\n", virt_to_bus ( adapter->tx_base ) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_process_tx_packets - process transmitted packets
|
||||
*
|
||||
* @v netdev network interface device structure
|
||||
**/
|
||||
static void e1000_process_tx_packets ( struct net_device *netdev )
|
||||
{
|
||||
struct e1000_adapter *adapter = netdev_priv ( netdev );
|
||||
uint32_t i;
|
||||
uint32_t tx_status;
|
||||
struct e1000_tx_desc *tx_curr_desc;
|
||||
|
||||
/* Check status of transmitted packets
|
||||
*/
|
||||
while ( ( i = adapter->tx_head ) != adapter->tx_tail ) {
|
||||
|
||||
tx_curr_desc = ( void * ) ( adapter->tx_base ) +
|
||||
( i * sizeof ( *adapter->tx_base ) );
|
||||
|
||||
tx_status = tx_curr_desc->upper.data;
|
||||
|
||||
/* if the packet at tx_head is not owned by hardware it is for us */
|
||||
if ( ! ( tx_status & E1000_TXD_STAT_DD ) )
|
||||
break;
|
||||
|
||||
DBG ( "Sent packet. tx_head: %d tx_tail: %d tx_status: %#08x\n",
|
||||
adapter->tx_head, adapter->tx_tail, tx_status );
|
||||
|
||||
if ( tx_status & ( E1000_TXD_STAT_EC | E1000_TXD_STAT_LC |
|
||||
E1000_TXD_STAT_TU ) ) {
|
||||
netdev_tx_complete_err ( netdev, adapter->tx_iobuf[i], -EINVAL );
|
||||
DBG ( "Error transmitting packet, tx_status: %#08x\n",
|
||||
tx_status );
|
||||
} else {
|
||||
netdev_tx_complete ( netdev, adapter->tx_iobuf[i] );
|
||||
DBG ( "Success transmitting packet, tx_status: %#08x\n",
|
||||
tx_status );
|
||||
}
|
||||
|
||||
/* Decrement count of used descriptors, clear this descriptor
|
||||
*/
|
||||
adapter->tx_fill_ctr--;
|
||||
memset ( tx_curr_desc, 0, sizeof ( *tx_curr_desc ) );
|
||||
|
||||
adapter->tx_head = ( adapter->tx_head + 1 ) % NUM_TX_DESC;
|
||||
}
|
||||
}
|
||||
|
||||
static void e1000_free_tx_resources ( struct e1000_adapter *adapter )
|
||||
{
|
||||
DBG ( "e1000_free_tx_resources\n" );
|
||||
|
||||
free_dma ( adapter->tx_base, adapter->tx_ring_size );
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_configure_tx - Configure 8254x Transmit Unit after Reset
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Configure the Tx unit of the MAC after a reset.
|
||||
**/
|
||||
static void e1000_configure_tx ( struct e1000_adapter *adapter )
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
uint32_t tctl;
|
||||
|
||||
DBG ( "e1000_configure_tx\n" );
|
||||
|
||||
E1000_WRITE_REG ( hw, E1000_TDBAH(0), 0 );
|
||||
E1000_WRITE_REG ( hw, E1000_TDBAL(0), virt_to_bus ( adapter->tx_base ) );
|
||||
E1000_WRITE_REG ( hw, E1000_TDLEN(0), adapter->tx_ring_size );
|
||||
|
||||
DBG ( "E1000_TDBAL(0): %#08x\n", E1000_READ_REG ( hw, E1000_TDBAL(0) ) );
|
||||
DBG ( "E1000_TDLEN(0): %d\n", E1000_READ_REG ( hw, E1000_TDLEN(0) ) );
|
||||
|
||||
/* Setup the HW Tx Head and Tail descriptor pointers */
|
||||
E1000_WRITE_REG ( hw, E1000_TDH(0), 0 );
|
||||
E1000_WRITE_REG ( hw, E1000_TDT(0), 0 );
|
||||
|
||||
adapter->tx_head = 0;
|
||||
adapter->tx_tail = 0;
|
||||
adapter->tx_fill_ctr = 0;
|
||||
|
||||
/* Setup Transmit Descriptor Settings for eop descriptor */
|
||||
tctl = E1000_TCTL_PSP | E1000_TCTL_EN |
|
||||
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT) |
|
||||
(E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT);
|
||||
|
||||
e1000_config_collision_dist ( hw );
|
||||
|
||||
E1000_WRITE_REG ( hw, E1000_TCTL, tctl );
|
||||
E1000_WRITE_FLUSH ( hw );
|
||||
}
|
||||
|
||||
static void e1000_free_rx_resources ( struct e1000_adapter *adapter )
|
||||
{
|
||||
int i;
|
||||
|
||||
DBG ( "e1000_free_rx_resources\n" );
|
||||
|
||||
free_dma ( adapter->rx_base, adapter->rx_ring_size );
|
||||
|
||||
for ( i = 0; i < NUM_RX_DESC; i++ ) {
|
||||
free_iob ( adapter->rx_iobuf[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_refill_rx_ring - allocate Rx io_buffers
|
||||
*
|
||||
* @v adapter e1000 private structure
|
||||
*
|
||||
* @ret rc Returns 0 on success, negative on failure
|
||||
**/
|
||||
static int e1000_refill_rx_ring ( struct e1000_adapter *adapter )
|
||||
{
|
||||
int i, rx_curr;
|
||||
int rc = 0;
|
||||
struct e1000_rx_desc *rx_curr_desc;
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
struct io_buffer *iob;
|
||||
|
||||
DBG ("e1000_refill_rx_ring\n");
|
||||
|
||||
for ( i = 0; i < NUM_RX_DESC; i++ ) {
|
||||
rx_curr = ( ( adapter->rx_curr + i ) % NUM_RX_DESC );
|
||||
rx_curr_desc = adapter->rx_base + rx_curr;
|
||||
|
||||
if ( rx_curr_desc->status & E1000_RXD_STAT_DD )
|
||||
continue;
|
||||
|
||||
if ( adapter->rx_iobuf[rx_curr] != NULL )
|
||||
continue;
|
||||
|
||||
DBG2 ( "Refilling rx desc %d\n", rx_curr );
|
||||
|
||||
iob = alloc_iob ( MAXIMUM_ETHERNET_VLAN_SIZE );
|
||||
adapter->rx_iobuf[rx_curr] = iob;
|
||||
|
||||
if ( ! iob ) {
|
||||
DBG ( "alloc_iob failed\n" );
|
||||
rc = -ENOMEM;
|
||||
break;
|
||||
} else {
|
||||
rx_curr_desc->buffer_addr = virt_to_bus ( iob->data );
|
||||
|
||||
E1000_WRITE_REG ( hw, E1000_RDT(0), rx_curr );
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_setup_rx_resources - allocate Rx resources (Descriptors)
|
||||
*
|
||||
* @v adapter e1000 private structure
|
||||
*
|
||||
* @ret rc Returns 0 on success, negative on failure
|
||||
**/
|
||||
static int e1000_setup_rx_resources ( struct e1000_adapter *adapter )
|
||||
{
|
||||
int i, rc = 0;
|
||||
|
||||
DBG ( "e1000_setup_rx_resources\n" );
|
||||
|
||||
/* Allocate receive descriptor ring memory.
|
||||
It must not cross a 64K boundary because of hardware errata
|
||||
*/
|
||||
|
||||
adapter->rx_base =
|
||||
malloc_dma ( adapter->rx_ring_size, adapter->rx_ring_size );
|
||||
|
||||
if ( ! adapter->rx_base ) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset ( adapter->rx_base, 0, adapter->rx_ring_size );
|
||||
|
||||
for ( i = 0; i < NUM_RX_DESC; i++ ) {
|
||||
/* let e1000_refill_rx_ring() io_buffer allocations */
|
||||
adapter->rx_iobuf[i] = NULL;
|
||||
}
|
||||
|
||||
/* allocate io_buffers */
|
||||
rc = e1000_refill_rx_ring ( adapter );
|
||||
if ( rc < 0 )
|
||||
e1000_free_rx_resources ( adapter );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_configure_rx - Configure 8254x Receive Unit after Reset
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Configure the Rx unit of the MAC after a reset.
|
||||
**/
|
||||
static void e1000_configure_rx ( struct e1000_adapter *adapter )
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
uint32_t rctl;
|
||||
|
||||
DBG ( "e1000_configure_rx\n" );
|
||||
|
||||
/* disable receives while setting up the descriptors */
|
||||
rctl = E1000_READ_REG ( hw, E1000_RCTL );
|
||||
E1000_WRITE_REG ( hw, E1000_RCTL, rctl & ~E1000_RCTL_EN );
|
||||
E1000_WRITE_FLUSH ( hw );
|
||||
mdelay(10);
|
||||
|
||||
adapter->rx_curr = 0;
|
||||
|
||||
/* Setup the HW Rx Head and Tail Descriptor Pointers and
|
||||
* the Base and Length of the Rx Descriptor Ring */
|
||||
|
||||
E1000_WRITE_REG ( hw, E1000_RDBAL(0), virt_to_bus ( adapter->rx_base ) );
|
||||
E1000_WRITE_REG ( hw, E1000_RDBAH(0), 0 );
|
||||
E1000_WRITE_REG ( hw, E1000_RDLEN(0), adapter->rx_ring_size );
|
||||
|
||||
E1000_WRITE_REG ( hw, E1000_RDH(0), 0 );
|
||||
E1000_WRITE_REG ( hw, E1000_RDT(0), NUM_RX_DESC - 1 );
|
||||
|
||||
/* Enable Receives */
|
||||
rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
|
||||
E1000_RCTL_MPE;
|
||||
E1000_WRITE_REG ( hw, E1000_RCTL, rctl );
|
||||
E1000_WRITE_FLUSH ( hw );
|
||||
|
||||
DBG ( "E1000_RDBAL(0): %#08x\n", E1000_READ_REG ( hw, E1000_RDBAL(0) ) );
|
||||
DBG ( "E1000_RDLEN(0): %d\n", E1000_READ_REG ( hw, E1000_RDLEN(0) ) );
|
||||
DBG ( "E1000_RCTL: %#08x\n", E1000_READ_REG ( hw, E1000_RCTL ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_process_rx_packets - process received packets
|
||||
*
|
||||
* @v netdev network interface device structure
|
||||
**/
|
||||
static void e1000_process_rx_packets ( struct net_device *netdev )
|
||||
{
|
||||
struct e1000_adapter *adapter = netdev_priv ( netdev );
|
||||
uint32_t i;
|
||||
uint32_t rx_status;
|
||||
uint32_t rx_len;
|
||||
uint32_t rx_err;
|
||||
struct e1000_rx_desc *rx_curr_desc;
|
||||
|
||||
/* Process received packets
|
||||
*/
|
||||
while ( 1 ) {
|
||||
|
||||
i = adapter->rx_curr;
|
||||
|
||||
rx_curr_desc = ( void * ) ( adapter->rx_base ) +
|
||||
( i * sizeof ( *adapter->rx_base ) );
|
||||
rx_status = rx_curr_desc->status;
|
||||
|
||||
DBG2 ( "Before DD Check RX_status: %#08x\n", rx_status );
|
||||
|
||||
if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
|
||||
break;
|
||||
|
||||
if ( adapter->rx_iobuf[i] == NULL )
|
||||
break;
|
||||
|
||||
DBG ( "E1000_RCTL = %#08x\n", E1000_READ_REG ( &adapter->hw, E1000_RCTL ) );
|
||||
|
||||
rx_len = rx_curr_desc->length;
|
||||
|
||||
DBG ( "Received packet, rx_curr: %d rx_status: %#08x rx_len: %d\n",
|
||||
i, rx_status, rx_len );
|
||||
|
||||
rx_err = rx_curr_desc->errors;
|
||||
|
||||
iob_put ( adapter->rx_iobuf[i], rx_len );
|
||||
|
||||
if ( rx_err & E1000_RXD_ERR_FRAME_ERR_MASK ) {
|
||||
|
||||
netdev_rx_err ( netdev, adapter->rx_iobuf[i], -EINVAL );
|
||||
DBG ( "e1000_poll: Corrupted packet received!"
|
||||
" rx_err: %#08x\n", rx_err );
|
||||
} else {
|
||||
/* Add this packet to the receive queue. */
|
||||
netdev_rx ( netdev, adapter->rx_iobuf[i] );
|
||||
}
|
||||
adapter->rx_iobuf[i] = NULL;
|
||||
|
||||
memset ( rx_curr_desc, 0, sizeof ( *rx_curr_desc ) );
|
||||
|
||||
adapter->rx_curr = ( adapter->rx_curr + 1 ) % NUM_RX_DESC;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_reset - Put e1000 NIC in known initial state
|
||||
*
|
||||
* @v adapter e1000 private structure
|
||||
**/
|
||||
void e1000_reset ( struct e1000_adapter *adapter )
|
||||
{
|
||||
struct e1000_mac_info *mac = &adapter->hw.mac;
|
||||
u32 pba = 0;
|
||||
|
||||
DBG ( "e1000_reset\n" );
|
||||
|
||||
switch (mac->type) {
|
||||
case e1000_82542:
|
||||
case e1000_82543:
|
||||
case e1000_82544:
|
||||
case e1000_82540:
|
||||
case e1000_82541:
|
||||
case e1000_82541_rev_2:
|
||||
pba = E1000_PBA_48K;
|
||||
break;
|
||||
case e1000_82545:
|
||||
case e1000_82545_rev_3:
|
||||
case e1000_82546:
|
||||
case e1000_82546_rev_3:
|
||||
pba = E1000_PBA_48K;
|
||||
break;
|
||||
case e1000_82547:
|
||||
case e1000_82547_rev_2:
|
||||
pba = E1000_PBA_30K;
|
||||
break;
|
||||
case e1000_undefined:
|
||||
case e1000_num_macs:
|
||||
break;
|
||||
}
|
||||
|
||||
E1000_WRITE_REG ( &adapter->hw, E1000_PBA, pba );
|
||||
|
||||
/* Allow time for pending master requests to run */
|
||||
e1000_reset_hw ( &adapter->hw );
|
||||
|
||||
if ( mac->type >= e1000_82544 )
|
||||
E1000_WRITE_REG ( &adapter->hw, E1000_WUC, 0 );
|
||||
|
||||
if ( e1000_init_hw ( &adapter->hw ) )
|
||||
DBG ( "Hardware Error\n" );
|
||||
|
||||
e1000_reset_adaptive ( &adapter->hw );
|
||||
e1000_get_phy_info ( &adapter->hw );
|
||||
|
||||
e1000_init_manageability ( adapter );
|
||||
}
|
||||
|
||||
/** Functions that implement the gPXE driver API **/
|
||||
|
||||
/**
|
||||
* e1000_close - Disables a network interface
|
||||
*
|
||||
* @v netdev network interface device structure
|
||||
*
|
||||
**/
|
||||
static void e1000_close ( struct net_device *netdev )
|
||||
{
|
||||
struct e1000_adapter *adapter = netdev_priv ( netdev );
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
uint32_t rctl;
|
||||
uint32_t icr;
|
||||
|
||||
DBG ( "e1000_close\n" );
|
||||
|
||||
/* Acknowledge interrupts */
|
||||
icr = E1000_READ_REG ( hw, E1000_ICR );
|
||||
|
||||
e1000_irq_disable ( adapter );
|
||||
|
||||
/* disable receives */
|
||||
rctl = E1000_READ_REG ( hw, E1000_RCTL );
|
||||
E1000_WRITE_REG ( hw, E1000_RCTL, rctl & ~E1000_RCTL_EN );
|
||||
E1000_WRITE_FLUSH ( hw );
|
||||
|
||||
e1000_reset_hw ( hw );
|
||||
|
||||
e1000_free_tx_resources ( adapter );
|
||||
e1000_free_rx_resources ( adapter );
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_transmit - Transmit a packet
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @v iobuf I/O buffer
|
||||
*
|
||||
* @ret rc Returns 0 on success, negative on failure
|
||||
*/
|
||||
static int e1000_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
|
||||
{
|
||||
struct e1000_adapter *adapter = netdev_priv( netdev );
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
uint32_t tx_curr = adapter->tx_tail;
|
||||
struct e1000_tx_desc *tx_curr_desc;
|
||||
|
||||
DBG ("e1000_transmit\n");
|
||||
|
||||
if ( adapter->tx_fill_ctr == NUM_TX_DESC ) {
|
||||
DBG ("TX overflow\n");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
/* Save pointer to iobuf we have been given to transmit,
|
||||
netdev_tx_complete() will need it later
|
||||
*/
|
||||
adapter->tx_iobuf[tx_curr] = iobuf;
|
||||
|
||||
tx_curr_desc = ( void * ) ( adapter->tx_base ) +
|
||||
( tx_curr * sizeof ( *adapter->tx_base ) );
|
||||
|
||||
DBG ( "tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
|
||||
DBG ( "tx_curr_desc + 16 = %#08lx\n", virt_to_bus ( tx_curr_desc ) + 16 );
|
||||
DBG ( "iobuf->data = %#08lx\n", virt_to_bus ( iobuf->data ) );
|
||||
|
||||
/* Add the packet to TX ring
|
||||
*/
|
||||
tx_curr_desc->buffer_addr =
|
||||
virt_to_bus ( iobuf->data );
|
||||
tx_curr_desc->lower.data =
|
||||
E1000_TXD_CMD_RPS | E1000_TXD_CMD_EOP |
|
||||
E1000_TXD_CMD_IFCS | iob_len ( iobuf );
|
||||
tx_curr_desc->upper.data = 0;
|
||||
|
||||
DBG ( "TX fill: %d tx_curr: %d addr: %#08lx len: %zd\n", adapter->tx_fill_ctr,
|
||||
tx_curr, virt_to_bus ( iobuf->data ), iob_len ( iobuf ) );
|
||||
|
||||
/* Point to next free descriptor */
|
||||
adapter->tx_tail = ( adapter->tx_tail + 1 ) % NUM_TX_DESC;
|
||||
adapter->tx_fill_ctr++;
|
||||
|
||||
/* Write new tail to NIC, making packet available for transmit
|
||||
*/
|
||||
wmb();
|
||||
E1000_WRITE_REG ( hw, E1000_TDT(0), adapter->tx_tail );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_poll - Poll for received packets
|
||||
*
|
||||
* @v netdev Network device
|
||||
*/
|
||||
static void e1000_poll ( struct net_device *netdev )
|
||||
{
|
||||
struct e1000_adapter *adapter = netdev_priv( netdev );
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
uint32_t icr;
|
||||
|
||||
DBGP ( "e1000_poll\n" );
|
||||
|
||||
/* Acknowledge interrupts */
|
||||
icr = E1000_READ_REG ( hw, E1000_ICR );
|
||||
if ( ! icr )
|
||||
return;
|
||||
|
||||
DBG ( "e1000_poll: intr_status = %#08x\n", icr );
|
||||
|
||||
e1000_process_tx_packets ( netdev );
|
||||
|
||||
e1000_process_rx_packets ( netdev );
|
||||
|
||||
e1000_refill_rx_ring(adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_irq - enable or Disable interrupts
|
||||
*
|
||||
* @v adapter e1000 adapter
|
||||
* @v action requested interrupt action
|
||||
**/
|
||||
static void e1000_irq ( struct net_device *netdev, int enable )
|
||||
{
|
||||
struct e1000_adapter *adapter = netdev_priv ( netdev );
|
||||
|
||||
DBG ( "e1000_irq\n" );
|
||||
|
||||
if ( enable ) {
|
||||
e1000_irq_enable ( adapter );
|
||||
} else {
|
||||
e1000_irq_disable ( adapter );
|
||||
}
|
||||
}
|
||||
|
||||
static struct net_device_operations e1000_operations;
|
||||
|
||||
/**
|
||||
* e1000_probe - Initial configuration of e1000 NIC
|
||||
*
|
||||
* @v pci PCI device
|
||||
* @v id PCI IDs
|
||||
*
|
||||
* @ret rc Return status code
|
||||
**/
|
||||
int e1000_probe ( struct pci_device *pdev,
|
||||
const struct pci_device_id *id __unused )
|
||||
{
|
||||
int i, err;
|
||||
struct net_device *netdev;
|
||||
struct e1000_adapter *adapter;
|
||||
unsigned long mmio_start, mmio_len;
|
||||
|
||||
DBG ( "e1000_probe\n" );
|
||||
|
||||
err = -ENOMEM;
|
||||
|
||||
/* Allocate net device ( also allocates memory for netdev->priv
|
||||
and makes netdev-priv point to it ) */
|
||||
netdev = alloc_etherdev ( sizeof ( struct e1000_adapter ) );
|
||||
if ( ! netdev )
|
||||
goto err_alloc_etherdev;
|
||||
|
||||
/* Associate e1000-specific network operations operations with
|
||||
* generic network device layer */
|
||||
netdev_init ( netdev, &e1000_operations );
|
||||
|
||||
/* Associate this network device with given PCI device */
|
||||
pci_set_drvdata ( pdev, netdev );
|
||||
netdev->dev = &pdev->dev;
|
||||
|
||||
/* Initialize driver private storage */
|
||||
adapter = netdev_priv ( netdev );
|
||||
memset ( adapter, 0, ( sizeof ( *adapter ) ) );
|
||||
|
||||
adapter->pdev = pdev;
|
||||
|
||||
adapter->ioaddr = pdev->ioaddr;
|
||||
adapter->hw.io_base = pdev->ioaddr;
|
||||
|
||||
adapter->irqno = pdev->irq;
|
||||
adapter->netdev = netdev;
|
||||
adapter->hw.back = adapter;
|
||||
|
||||
adapter->tx_ring_size = sizeof ( *adapter->tx_base ) * NUM_TX_DESC;
|
||||
adapter->rx_ring_size = sizeof ( *adapter->rx_base ) * NUM_RX_DESC;
|
||||
|
||||
mmio_start = pci_bar_start ( pdev, PCI_BASE_ADDRESS_0 );
|
||||
mmio_len = pci_bar_size ( pdev, PCI_BASE_ADDRESS_0 );
|
||||
|
||||
DBG ( "mmio_start: %#08lx\n", mmio_start );
|
||||
DBG ( "mmio_len: %#08lx\n", mmio_len );
|
||||
|
||||
/* Fix up PCI device */
|
||||
adjust_pci_device ( pdev );
|
||||
|
||||
err = -EIO;
|
||||
|
||||
adapter->hw.hw_addr = ioremap ( mmio_start, mmio_len );
|
||||
DBG ( "adapter->hw.hw_addr: %p\n", adapter->hw.hw_addr );
|
||||
|
||||
if ( ! adapter->hw.hw_addr )
|
||||
goto err_ioremap;
|
||||
|
||||
/* Hardware features, flags and workarounds */
|
||||
if (adapter->hw.mac.type >= e1000_82540) {
|
||||
adapter->flags |= E1000_FLAG_HAS_SMBUS;
|
||||
adapter->flags |= E1000_FLAG_HAS_INTR_MODERATION;
|
||||
}
|
||||
|
||||
if (adapter->hw.mac.type == e1000_82543)
|
||||
adapter->flags |= E1000_FLAG_BAD_TX_CARRIER_STATS_FD;
|
||||
|
||||
adapter->hw.phy.autoneg_wait_to_complete = true;
|
||||
adapter->hw.mac.adaptive_ifs = true;
|
||||
|
||||
/* setup the private structure */
|
||||
if ( ( err = e1000_sw_init ( adapter ) ) )
|
||||
goto err_sw_init;
|
||||
|
||||
if ((err = e1000_init_mac_params(&adapter->hw)))
|
||||
goto err_hw_init;
|
||||
|
||||
if ((err = e1000_init_nvm_params(&adapter->hw)))
|
||||
goto err_hw_init;
|
||||
|
||||
/* Force auto-negotiated speed and duplex */
|
||||
adapter->hw.mac.autoneg = 1;
|
||||
|
||||
if ((err = e1000_init_phy_params(&adapter->hw)))
|
||||
goto err_hw_init;
|
||||
|
||||
DBG ( "adapter->hw.mac.type: %#08x\n", adapter->hw.mac.type );
|
||||
|
||||
/* before reading the EEPROM, reset the controller to
|
||||
* put the device in a known good starting state
|
||||
*/
|
||||
err = e1000_reset_hw ( &adapter->hw );
|
||||
if ( err < 0 ) {
|
||||
DBG ( "Hardware Initialization Failed\n" );
|
||||
goto err_reset;
|
||||
}
|
||||
/* make sure the NVM is good */
|
||||
|
||||
if ( e1000_validate_nvm_checksum(&adapter->hw) < 0 ) {
|
||||
DBG ( "The NVM Checksum Is Not Valid\n" );
|
||||
err = -EIO;
|
||||
goto err_eeprom;
|
||||
}
|
||||
|
||||
/* copy the MAC address out of the EEPROM */
|
||||
if ( e1000_read_mac_addr ( &adapter->hw ) )
|
||||
DBG ( "EEPROM Read Error\n" );
|
||||
|
||||
memcpy ( netdev->hw_addr, adapter->hw.mac.perm_addr, ETH_ALEN );
|
||||
|
||||
/* reset the hardware with the new settings */
|
||||
e1000_reset ( adapter );
|
||||
|
||||
/* Mark as link up; we don't yet handle link state */
|
||||
netdev_link_up ( netdev );
|
||||
|
||||
if ( ( err = register_netdev ( netdev ) ) != 0)
|
||||
goto err_register;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
DBG ("%02x%s", netdev->ll_addr[i], i == 5 ? "\n" : ":");
|
||||
|
||||
DBG ( "e1000_probe succeeded!\n" );
|
||||
|
||||
/* No errors, return success */
|
||||
return 0;
|
||||
|
||||
/* Error return paths */
|
||||
err_reset:
|
||||
err_register:
|
||||
err_hw_init:
|
||||
err_eeprom:
|
||||
if (!e1000_check_reset_block(&adapter->hw))
|
||||
e1000_phy_hw_reset(&adapter->hw);
|
||||
if (adapter->hw.flash_address)
|
||||
iounmap(adapter->hw.flash_address);
|
||||
err_sw_init:
|
||||
iounmap ( adapter->hw.hw_addr );
|
||||
err_ioremap:
|
||||
netdev_put ( netdev );
|
||||
err_alloc_etherdev:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_remove - Device Removal Routine
|
||||
*
|
||||
* @v pdev PCI device information struct
|
||||
*
|
||||
**/
|
||||
void e1000_remove ( struct pci_device *pdev )
|
||||
{
|
||||
struct net_device *netdev = pci_get_drvdata ( pdev );
|
||||
struct e1000_adapter *adapter = netdev_priv ( netdev );
|
||||
|
||||
DBG ( "e1000_remove\n" );
|
||||
|
||||
if ( adapter->hw.flash_address )
|
||||
iounmap ( adapter->hw.flash_address );
|
||||
if ( adapter->hw.hw_addr )
|
||||
iounmap ( adapter->hw.hw_addr );
|
||||
|
||||
unregister_netdev ( netdev );
|
||||
e1000_reset_hw ( &adapter->hw );
|
||||
netdev_nullify ( netdev );
|
||||
netdev_put ( netdev );
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_open - Called when a network interface is made active
|
||||
*
|
||||
* @v netdev network interface device structure
|
||||
* @ret rc Return status code, 0 on success, negative value on failure
|
||||
*
|
||||
**/
|
||||
static int e1000_open ( struct net_device *netdev )
|
||||
{
|
||||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
int err;
|
||||
|
||||
DBG ( "e1000_open\n" );
|
||||
|
||||
/* allocate transmit descriptors */
|
||||
err = e1000_setup_tx_resources ( adapter );
|
||||
if ( err ) {
|
||||
DBG ( "Error setting up TX resources!\n" );
|
||||
goto err_setup_tx;
|
||||
}
|
||||
|
||||
/* allocate receive descriptors */
|
||||
err = e1000_setup_rx_resources ( adapter );
|
||||
if ( err ) {
|
||||
DBG ( "Error setting up RX resources!\n" );
|
||||
goto err_setup_rx;
|
||||
}
|
||||
|
||||
e1000_configure_tx ( adapter );
|
||||
|
||||
e1000_configure_rx ( adapter );
|
||||
|
||||
DBG ( "E1000_RXDCTL(0): %#08x\n", E1000_READ_REG ( &adapter->hw, E1000_RXDCTL(0) ) );
|
||||
|
||||
return 0;
|
||||
|
||||
err_setup_rx:
|
||||
e1000_free_tx_resources ( adapter );
|
||||
err_setup_tx:
|
||||
e1000_reset ( adapter );
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/** e1000 net device operations */
|
||||
static struct net_device_operations e1000_operations = {
|
||||
.open = e1000_open,
|
||||
.close = e1000_close,
|
||||
.transmit = e1000_transmit,
|
||||
.poll = e1000_poll,
|
||||
.irq = e1000_irq,
|
||||
};
|
||||
@@ -0,0 +1,389 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#if 0
|
||||
|
||||
#include "e1000_api.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;
|
||||
|
||||
DEBUGFUNC("e1000_calculate_checksum");
|
||||
|
||||
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;
|
||||
|
||||
DEBUGFUNC("e1000_mng_enable_host_if_generic");
|
||||
|
||||
/* Check that the host interface is enabled. */
|
||||
hicr = E1000_READ_REG(hw, E1000_HICR);
|
||||
if ((hicr & E1000_HICR_EN) == 0) {
|
||||
DEBUGOUT("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 = E1000_READ_REG(hw, E1000_HICR);
|
||||
if (!(hicr & E1000_HICR_C))
|
||||
break;
|
||||
msec_delay_irq(1);
|
||||
}
|
||||
|
||||
if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
|
||||
DEBUGOUT("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;
|
||||
|
||||
DEBUGFUNC("e1000_check_mng_mode_generic");
|
||||
|
||||
fwsm = E1000_READ_REG(hw, E1000_FWSM);
|
||||
|
||||
return (fwsm & E1000_FWSM_MODE_MASK) ==
|
||||
(E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_enable_tx_pkt_filtering_generic - 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 e1000_enable_tx_pkt_filtering_generic(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;
|
||||
|
||||
DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_mng_write_dhcp_info_generic - 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 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
|
||||
u16 length)
|
||||
{
|
||||
struct e1000_host_mng_command_header hdr;
|
||||
s32 ret_val;
|
||||
u32 hicr;
|
||||
|
||||
DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
|
||||
|
||||
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 = E1000_READ_REG(hw, E1000_HICR);
|
||||
E1000_WRITE_REG(hw, E1000_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);
|
||||
|
||||
DEBUGFUNC("e1000_mng_write_cmd_header_generic");
|
||||
|
||||
/* 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));
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
DEBUGFUNC("e1000_mng_host_if_write_generic");
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_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 e1000_enable_mng_pass_thru(struct e1000_hw *hw)
|
||||
{
|
||||
u32 manc;
|
||||
u32 fwsm, factps;
|
||||
bool ret_val = false;
|
||||
|
||||
DEBUGFUNC("e1000_enable_mng_pass_thru");
|
||||
|
||||
if (!hw->mac.asf_firmware_present)
|
||||
goto out;
|
||||
|
||||
manc = E1000_READ_REG(hw, E1000_MANC);
|
||||
|
||||
if (!(manc & E1000_MANC_RCV_TCO_EN) ||
|
||||
!(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
|
||||
goto out;
|
||||
|
||||
if (hw->mac.arc_subsystem_valid) {
|
||||
fwsm = E1000_READ_REG(hw, E1000_FWSM);
|
||||
factps = E1000_READ_REG(hw, E1000_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;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,84 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#ifndef _E1000_MANAGE_H_
|
||||
#define _E1000_MANAGE_H_
|
||||
|
||||
bool e1000_check_mng_mode_generic(struct e1000_hw *hw);
|
||||
bool e1000_enable_tx_pkt_filtering_generic(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 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw,
|
||||
u8 *buffer, u16 length);
|
||||
bool e1000_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
|
||||
};
|
||||
|
||||
#define E1000_FACTPS_MNGCG 0x20000000
|
||||
|
||||
#define E1000_FWSM_MODE_MASK 0xE
|
||||
#define E1000_FWSM_MODE_SHIFT 1
|
||||
|
||||
#define E1000_MNG_IAMT_MODE 0x3
|
||||
#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10
|
||||
#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0
|
||||
#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10
|
||||
#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64
|
||||
#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1
|
||||
#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2
|
||||
|
||||
#define E1000_VFTA_ENTRY_SHIFT 5
|
||||
#define E1000_VFTA_ENTRY_MASK 0x7F
|
||||
#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F
|
||||
|
||||
#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */
|
||||
#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */
|
||||
#define E1000_HI_COMMAND_TIMEOUT 500 /* Process HI command limit */
|
||||
|
||||
#define E1000_HICR_EN 0x01 /* Enable bit - RO */
|
||||
/* Driver sets this bit when done to put command in RAM */
|
||||
#define E1000_HICR_C 0x02
|
||||
#define E1000_HICR_SV 0x04 /* Status Validity */
|
||||
#define E1000_HICR_FW_RESET_ENABLE 0x40
|
||||
#define E1000_HICR_FW_RESET 0x80
|
||||
|
||||
/* Intel(R) Active Management Technology signature */
|
||||
#define E1000_IAMT_SIGNATURE 0x544D4149
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,923 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include "e1000_api.h"
|
||||
|
||||
static void e1000_reload_nvm_generic(struct e1000_hw *hw);
|
||||
|
||||
/**
|
||||
* e1000_init_nvm_ops_generic - Initialize NVM function pointers
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Setups up the function pointers to no-op functions
|
||||
**/
|
||||
void e1000_init_nvm_ops_generic(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
DEBUGFUNC("e1000_init_nvm_ops_generic");
|
||||
|
||||
/* Initialize function pointers */
|
||||
nvm->ops.init_params = e1000_null_ops_generic;
|
||||
nvm->ops.acquire = e1000_null_ops_generic;
|
||||
nvm->ops.read = e1000_null_read_nvm;
|
||||
nvm->ops.release = e1000_null_nvm_generic;
|
||||
nvm->ops.reload = e1000_reload_nvm_generic;
|
||||
nvm->ops.update = e1000_null_ops_generic;
|
||||
nvm->ops.valid_led_default = e1000_null_led_default;
|
||||
nvm->ops.validate = e1000_null_ops_generic;
|
||||
nvm->ops.write = e1000_null_write_nvm;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_null_nvm_read - No-op function, return 0
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
s32 e1000_null_read_nvm(struct e1000_hw *hw __unused, u16 a __unused,
|
||||
u16 b __unused, u16 *c __unused)
|
||||
{
|
||||
DEBUGFUNC("e1000_null_read_nvm");
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_null_nvm_generic - No-op function, return void
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
void e1000_null_nvm_generic(struct e1000_hw *hw __unused)
|
||||
{
|
||||
DEBUGFUNC("e1000_null_nvm_generic");
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_null_led_default - No-op function, return 0
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
s32 e1000_null_led_default(struct e1000_hw *hw __unused,
|
||||
u16 *data __unused)
|
||||
{
|
||||
DEBUGFUNC("e1000_null_led_default");
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_null_write_nvm - No-op function, return 0
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
s32 e1000_null_write_nvm(struct e1000_hw *hw __unused, u16 a __unused,
|
||||
u16 b __unused, u16 *c __unused)
|
||||
{
|
||||
DEBUGFUNC("e1000_null_write_nvm");
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_raise_eec_clk - Raise EEPROM clock
|
||||
* @hw: pointer to the HW structure
|
||||
* @eecd: pointer to the EEPROM
|
||||
*
|
||||
* Enable/Raise the EEPROM clock bit.
|
||||
**/
|
||||
static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
|
||||
{
|
||||
*eecd = *eecd | E1000_EECD_SK;
|
||||
E1000_WRITE_REG(hw, E1000_EECD, *eecd);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
usec_delay(hw->nvm.delay_usec);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_lower_eec_clk - Lower EEPROM clock
|
||||
* @hw: pointer to the HW structure
|
||||
* @eecd: pointer to the EEPROM
|
||||
*
|
||||
* Clear/Lower the EEPROM clock bit.
|
||||
**/
|
||||
static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
|
||||
{
|
||||
*eecd = *eecd & ~E1000_EECD_SK;
|
||||
E1000_WRITE_REG(hw, E1000_EECD, *eecd);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
usec_delay(hw->nvm.delay_usec);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_shift_out_eec_bits - Shift data bits our to the EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
* @data: data to send to the EEPROM
|
||||
* @count: number of bits to shift out
|
||||
*
|
||||
* We need to shift 'count' bits out to the EEPROM. So, the value in the
|
||||
* "data" parameter will be shifted out to the EEPROM one bit at a time.
|
||||
* In order to do this, "data" must be broken down into bits.
|
||||
**/
|
||||
static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
|
||||
u32 mask;
|
||||
|
||||
DEBUGFUNC("e1000_shift_out_eec_bits");
|
||||
|
||||
mask = 0x01 << (count - 1);
|
||||
if (nvm->type == e1000_nvm_eeprom_microwire)
|
||||
eecd &= ~E1000_EECD_DO;
|
||||
else
|
||||
if (nvm->type == e1000_nvm_eeprom_spi)
|
||||
eecd |= E1000_EECD_DO;
|
||||
|
||||
do {
|
||||
eecd &= ~E1000_EECD_DI;
|
||||
|
||||
if (data & mask)
|
||||
eecd |= E1000_EECD_DI;
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
|
||||
usec_delay(nvm->delay_usec);
|
||||
|
||||
e1000_raise_eec_clk(hw, &eecd);
|
||||
e1000_lower_eec_clk(hw, &eecd);
|
||||
|
||||
mask >>= 1;
|
||||
} while (mask);
|
||||
|
||||
eecd &= ~E1000_EECD_DI;
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_shift_in_eec_bits - Shift data bits in from the EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
* @count: number of bits to shift in
|
||||
*
|
||||
* In order to read a register from the EEPROM, we need to shift 'count' bits
|
||||
* in from the EEPROM. Bits are "shifted in" by raising the clock input to
|
||||
* the EEPROM (setting the SK bit), and then reading the value of the data out
|
||||
* "DO" bit. During this "shifting in" process the data in "DI" bit should
|
||||
* always be clear.
|
||||
**/
|
||||
static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
|
||||
{
|
||||
u32 eecd;
|
||||
u32 i;
|
||||
u16 data;
|
||||
|
||||
DEBUGFUNC("e1000_shift_in_eec_bits");
|
||||
|
||||
eecd = E1000_READ_REG(hw, E1000_EECD);
|
||||
|
||||
eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
|
||||
data = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
data <<= 1;
|
||||
e1000_raise_eec_clk(hw, &eecd);
|
||||
|
||||
eecd = E1000_READ_REG(hw, E1000_EECD);
|
||||
|
||||
eecd &= ~E1000_EECD_DI;
|
||||
if (eecd & E1000_EECD_DO)
|
||||
data |= 1;
|
||||
|
||||
e1000_lower_eec_clk(hw, &eecd);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion
|
||||
* @hw: pointer to the HW structure
|
||||
* @ee_reg: EEPROM flag for polling
|
||||
*
|
||||
* Polls the EEPROM status bit for either read or write completion based
|
||||
* upon the value of 'ee_reg'.
|
||||
**/
|
||||
s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
|
||||
{
|
||||
u32 attempts = 100000;
|
||||
u32 i, reg = 0;
|
||||
s32 ret_val = -E1000_ERR_NVM;
|
||||
|
||||
DEBUGFUNC("e1000_poll_eerd_eewr_done");
|
||||
|
||||
for (i = 0; i < attempts; i++) {
|
||||
if (ee_reg == E1000_NVM_POLL_READ)
|
||||
reg = E1000_READ_REG(hw, E1000_EERD);
|
||||
else
|
||||
reg = E1000_READ_REG(hw, E1000_EEWR);
|
||||
|
||||
if (reg & E1000_NVM_RW_REG_DONE) {
|
||||
ret_val = E1000_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
usec_delay(5);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_acquire_nvm_generic - Generic request for access to EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Set the EEPROM access request bit and wait for EEPROM access grant bit.
|
||||
* Return successful if access grant bit set, else clear the request for
|
||||
* EEPROM access and return -E1000_ERR_NVM (-1).
|
||||
**/
|
||||
s32 e1000_acquire_nvm_generic(struct e1000_hw *hw)
|
||||
{
|
||||
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
|
||||
s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
|
||||
DEBUGFUNC("e1000_acquire_nvm_generic");
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ);
|
||||
eecd = E1000_READ_REG(hw, E1000_EECD);
|
||||
|
||||
while (timeout) {
|
||||
if (eecd & E1000_EECD_GNT)
|
||||
break;
|
||||
usec_delay(5);
|
||||
eecd = E1000_READ_REG(hw, E1000_EECD);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
eecd &= ~E1000_EECD_REQ;
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd);
|
||||
DEBUGOUT("Could not acquire NVM grant\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_standby_nvm - Return EEPROM to standby state
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Return the EEPROM to a standby state.
|
||||
**/
|
||||
static void e1000_standby_nvm(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
|
||||
|
||||
DEBUGFUNC("e1000_standby_nvm");
|
||||
|
||||
if (nvm->type == e1000_nvm_eeprom_microwire) {
|
||||
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
usec_delay(nvm->delay_usec);
|
||||
|
||||
e1000_raise_eec_clk(hw, &eecd);
|
||||
|
||||
/* Select EEPROM */
|
||||
eecd |= E1000_EECD_CS;
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
usec_delay(nvm->delay_usec);
|
||||
|
||||
e1000_lower_eec_clk(hw, &eecd);
|
||||
} else
|
||||
if (nvm->type == e1000_nvm_eeprom_spi) {
|
||||
/* Toggle CS to flush commands */
|
||||
eecd |= E1000_EECD_CS;
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
usec_delay(nvm->delay_usec);
|
||||
eecd &= ~E1000_EECD_CS;
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
usec_delay(nvm->delay_usec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_stop_nvm - Terminate EEPROM command
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Terminates the current command by inverting the EEPROM's chip select pin.
|
||||
**/
|
||||
void e1000_stop_nvm(struct e1000_hw *hw)
|
||||
{
|
||||
u32 eecd;
|
||||
|
||||
DEBUGFUNC("e1000_stop_nvm");
|
||||
|
||||
eecd = E1000_READ_REG(hw, E1000_EECD);
|
||||
if (hw->nvm.type == e1000_nvm_eeprom_spi) {
|
||||
/* Pull CS high */
|
||||
eecd |= E1000_EECD_CS;
|
||||
e1000_lower_eec_clk(hw, &eecd);
|
||||
} else if (hw->nvm.type == e1000_nvm_eeprom_microwire) {
|
||||
/* CS on Microwire is active-high */
|
||||
eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd);
|
||||
e1000_raise_eec_clk(hw, &eecd);
|
||||
e1000_lower_eec_clk(hw, &eecd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_release_nvm_generic - Release exclusive access to EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Stop any current commands to the EEPROM and clear the EEPROM request bit.
|
||||
**/
|
||||
void e1000_release_nvm_generic(struct e1000_hw *hw)
|
||||
{
|
||||
u32 eecd;
|
||||
|
||||
DEBUGFUNC("e1000_release_nvm_generic");
|
||||
|
||||
e1000_stop_nvm(hw);
|
||||
|
||||
eecd = E1000_READ_REG(hw, E1000_EECD);
|
||||
eecd &= ~E1000_EECD_REQ;
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_ready_nvm_eeprom - Prepares EEPROM for read/write
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Setups the EEPROM for reading and writing.
|
||||
**/
|
||||
static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u16 timeout = 0;
|
||||
u8 spi_stat_reg;
|
||||
|
||||
DEBUGFUNC("e1000_ready_nvm_eeprom");
|
||||
|
||||
if (nvm->type == e1000_nvm_eeprom_microwire) {
|
||||
/* Clear SK and DI */
|
||||
eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd);
|
||||
/* Set CS */
|
||||
eecd |= E1000_EECD_CS;
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd);
|
||||
} else
|
||||
if (nvm->type == e1000_nvm_eeprom_spi) {
|
||||
/* Clear SK and CS */
|
||||
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
|
||||
E1000_WRITE_REG(hw, E1000_EECD, eecd);
|
||||
usec_delay(1);
|
||||
timeout = NVM_MAX_RETRY_SPI;
|
||||
|
||||
/*
|
||||
* Read "Status Register" repeatedly until the LSB is cleared.
|
||||
* The EEPROM will signal that the command has been completed
|
||||
* by clearing bit 0 of the internal status register. If it's
|
||||
* not cleared within 'timeout', then error out.
|
||||
*/
|
||||
while (timeout) {
|
||||
e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
|
||||
hw->nvm.opcode_bits);
|
||||
spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8);
|
||||
if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
|
||||
break;
|
||||
|
||||
usec_delay(5);
|
||||
e1000_standby_nvm(hw);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
DEBUGOUT("SPI NVM Status error\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_read_nvm_spi - Read EEPROM's using SPI
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset of word in the EEPROM to read
|
||||
* @words: number of words to read
|
||||
* @data: word read from the EEPROM
|
||||
*
|
||||
* Reads a 16 bit word from the EEPROM.
|
||||
**/
|
||||
s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 i = 0;
|
||||
s32 ret_val;
|
||||
u16 word_in;
|
||||
u8 read_opcode = NVM_READ_OPCODE_SPI;
|
||||
|
||||
DEBUGFUNC("e1000_read_nvm_spi");
|
||||
|
||||
/*
|
||||
* A check for invalid values: offset too large, too many words,
|
||||
* and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
DEBUGOUT("nvm parameter(s) out of bounds\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = nvm->ops.acquire(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
ret_val = e1000_ready_nvm_eeprom(hw);
|
||||
if (ret_val)
|
||||
goto release;
|
||||
|
||||
e1000_standby_nvm(hw);
|
||||
|
||||
if ((nvm->address_bits == 8) && (offset >= 128))
|
||||
read_opcode |= NVM_A8_OPCODE_SPI;
|
||||
|
||||
/* Send the READ command (opcode + addr) */
|
||||
e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
|
||||
e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
|
||||
|
||||
/*
|
||||
* Read the data. SPI NVMs increment the address with each byte
|
||||
* read and will roll over if reading beyond the end. This allows
|
||||
* us to read the whole NVM from any offset
|
||||
*/
|
||||
for (i = 0; i < words; i++) {
|
||||
word_in = e1000_shift_in_eec_bits(hw, 16);
|
||||
data[i] = (word_in >> 8) | (word_in << 8);
|
||||
}
|
||||
|
||||
release:
|
||||
nvm->ops.release(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_read_nvm_microwire - Reads EEPROM's using microwire
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset of word in the EEPROM to read
|
||||
* @words: number of words to read
|
||||
* @data: word read from the EEPROM
|
||||
*
|
||||
* Reads a 16 bit word from the EEPROM.
|
||||
**/
|
||||
s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
|
||||
u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 i = 0;
|
||||
s32 ret_val;
|
||||
u8 read_opcode = NVM_READ_OPCODE_MICROWIRE;
|
||||
|
||||
DEBUGFUNC("e1000_read_nvm_microwire");
|
||||
|
||||
/*
|
||||
* A check for invalid values: offset too large, too many words,
|
||||
* and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
DEBUGOUT("nvm parameter(s) out of bounds\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = nvm->ops.acquire(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
ret_val = e1000_ready_nvm_eeprom(hw);
|
||||
if (ret_val)
|
||||
goto release;
|
||||
|
||||
for (i = 0; i < words; i++) {
|
||||
/* Send the READ command (opcode + addr) */
|
||||
e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
|
||||
e1000_shift_out_eec_bits(hw, (u16)(offset + i),
|
||||
nvm->address_bits);
|
||||
|
||||
/*
|
||||
* Read the data. For microwire, each word requires the
|
||||
* overhead of setup and tear-down.
|
||||
*/
|
||||
data[i] = e1000_shift_in_eec_bits(hw, 16);
|
||||
e1000_standby_nvm(hw);
|
||||
}
|
||||
|
||||
release:
|
||||
nvm->ops.release(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_read_nvm_eerd - Reads EEPROM using EERD register
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset of word in the EEPROM to read
|
||||
* @words: number of words to read
|
||||
* @data: word read from the EEPROM
|
||||
*
|
||||
* Reads a 16 bit word from the EEPROM using the EERD register.
|
||||
**/
|
||||
s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 i, eerd = 0;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
|
||||
DEBUGFUNC("e1000_read_nvm_eerd");
|
||||
|
||||
/*
|
||||
* A check for invalid values: offset too large, too many words,
|
||||
* too many words for the offset, and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
DEBUGOUT("nvm parameter(s) out of bounds\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < words; i++) {
|
||||
eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) +
|
||||
E1000_NVM_RW_REG_START;
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_EERD, eerd);
|
||||
ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
|
||||
if (ret_val)
|
||||
break;
|
||||
|
||||
data[i] = (E1000_READ_REG(hw, E1000_EERD) >>
|
||||
E1000_NVM_RW_REG_DATA);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_write_nvm_spi - Write to EEPROM using SPI
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset within the EEPROM to be written to
|
||||
* @words: number of words to write
|
||||
* @data: 16 bit word(s) to be written to the EEPROM
|
||||
*
|
||||
* Writes data to EEPROM at offset using SPI interface.
|
||||
*
|
||||
* If e1000_update_nvm_checksum is not called after this function , the
|
||||
* EEPROM will most likely contain an invalid checksum.
|
||||
**/
|
||||
s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
s32 ret_val;
|
||||
u16 widx = 0;
|
||||
|
||||
DEBUGFUNC("e1000_write_nvm_spi");
|
||||
|
||||
/*
|
||||
* A check for invalid values: offset too large, too many words,
|
||||
* and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
DEBUGOUT("nvm parameter(s) out of bounds\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = nvm->ops.acquire(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
while (widx < words) {
|
||||
u8 write_opcode = NVM_WRITE_OPCODE_SPI;
|
||||
|
||||
ret_val = e1000_ready_nvm_eeprom(hw);
|
||||
if (ret_val)
|
||||
goto release;
|
||||
|
||||
e1000_standby_nvm(hw);
|
||||
|
||||
/* Send the WRITE ENABLE command (8 bit opcode) */
|
||||
e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
|
||||
nvm->opcode_bits);
|
||||
|
||||
e1000_standby_nvm(hw);
|
||||
|
||||
/*
|
||||
* Some SPI eeproms use the 8th address bit embedded in the
|
||||
* opcode
|
||||
*/
|
||||
if ((nvm->address_bits == 8) && (offset >= 128))
|
||||
write_opcode |= NVM_A8_OPCODE_SPI;
|
||||
|
||||
/* Send the Write command (8-bit opcode + addr) */
|
||||
e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
|
||||
e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
|
||||
nvm->address_bits);
|
||||
|
||||
/* Loop to allow for up to whole page write of eeprom */
|
||||
while (widx < words) {
|
||||
u16 word_out = data[widx];
|
||||
word_out = (word_out >> 8) | (word_out << 8);
|
||||
e1000_shift_out_eec_bits(hw, word_out, 16);
|
||||
widx++;
|
||||
|
||||
if ((((offset + widx) * 2) % nvm->page_size) == 0) {
|
||||
e1000_standby_nvm(hw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msec_delay(10);
|
||||
release:
|
||||
nvm->ops.release(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_write_nvm_microwire - Writes EEPROM using microwire
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset within the EEPROM to be written to
|
||||
* @words: number of words to write
|
||||
* @data: 16 bit word(s) to be written to the EEPROM
|
||||
*
|
||||
* Writes data to EEPROM at offset using microwire interface.
|
||||
*
|
||||
* If e1000_update_nvm_checksum is not called after this function , the
|
||||
* EEPROM will most likely contain an invalid checksum.
|
||||
**/
|
||||
s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
|
||||
u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
s32 ret_val;
|
||||
u32 eecd;
|
||||
u16 words_written = 0;
|
||||
u16 widx = 0;
|
||||
|
||||
DEBUGFUNC("e1000_write_nvm_microwire");
|
||||
|
||||
/*
|
||||
* A check for invalid values: offset too large, too many words,
|
||||
* and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
DEBUGOUT("nvm parameter(s) out of bounds\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = nvm->ops.acquire(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
ret_val = e1000_ready_nvm_eeprom(hw);
|
||||
if (ret_val)
|
||||
goto release;
|
||||
|
||||
e1000_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE,
|
||||
(u16)(nvm->opcode_bits + 2));
|
||||
|
||||
e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
|
||||
|
||||
e1000_standby_nvm(hw);
|
||||
|
||||
while (words_written < words) {
|
||||
e1000_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE,
|
||||
nvm->opcode_bits);
|
||||
|
||||
e1000_shift_out_eec_bits(hw, (u16)(offset + words_written),
|
||||
nvm->address_bits);
|
||||
|
||||
e1000_shift_out_eec_bits(hw, data[words_written], 16);
|
||||
|
||||
e1000_standby_nvm(hw);
|
||||
|
||||
for (widx = 0; widx < 200; widx++) {
|
||||
eecd = E1000_READ_REG(hw, E1000_EECD);
|
||||
if (eecd & E1000_EECD_DO)
|
||||
break;
|
||||
usec_delay(50);
|
||||
}
|
||||
|
||||
if (widx == 200) {
|
||||
DEBUGOUT("NVM Write did not complete\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto release;
|
||||
}
|
||||
|
||||
e1000_standby_nvm(hw);
|
||||
|
||||
words_written++;
|
||||
}
|
||||
|
||||
e1000_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE,
|
||||
(u16)(nvm->opcode_bits + 2));
|
||||
|
||||
e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
|
||||
|
||||
release:
|
||||
nvm->ops.release(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_read_pba_num_generic - Read device part number
|
||||
* @hw: pointer to the HW structure
|
||||
* @pba_num: pointer to device part number
|
||||
*
|
||||
* Reads the product board assembly (PBA) number from the EEPROM and stores
|
||||
* the value in pba_num.
|
||||
**/
|
||||
s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 nvm_data;
|
||||
|
||||
DEBUGFUNC("e1000_read_pba_num_generic");
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
*pba_num = (u32)(nvm_data << 16);
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
*pba_num |= nvm_data;
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_read_mac_addr_generic - Read device MAC address
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Reads the device MAC address from the EEPROM and stores the value.
|
||||
* Since devices with two ports use the same EEPROM, we increment the
|
||||
* last bit in the MAC address for the second port.
|
||||
**/
|
||||
s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
|
||||
{
|
||||
u32 rar_high;
|
||||
u32 rar_low;
|
||||
u16 i;
|
||||
|
||||
rar_high = E1000_READ_REG(hw, E1000_RAH(0));
|
||||
rar_low = E1000_READ_REG(hw, E1000_RAL(0));
|
||||
|
||||
for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
|
||||
hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
|
||||
|
||||
for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
|
||||
hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
|
||||
|
||||
for (i = 0; i < ETH_ADDR_LEN; i++)
|
||||
hw->mac.addr[i] = hw->mac.perm_addr[i];
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_validate_nvm_checksum_generic - Validate EEPROM checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Calculates the EEPROM checksum by reading/adding each word of the EEPROM
|
||||
* and then verifies that the sum of the EEPROM is equal to 0xBABA.
|
||||
**/
|
||||
s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u16 checksum = 0;
|
||||
u16 i, nvm_data;
|
||||
|
||||
DEBUGFUNC("e1000_validate_nvm_checksum_generic");
|
||||
|
||||
for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
|
||||
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
checksum += nvm_data;
|
||||
}
|
||||
|
||||
if (checksum != (u16) NVM_SUM) {
|
||||
DEBUGOUT("NVM Checksum Invalid\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_update_nvm_checksum_generic - Update EEPROM checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Updates the EEPROM checksum by reading/adding each word of the EEPROM
|
||||
* up to the checksum. Then calculates the EEPROM checksum and writes the
|
||||
* value to the EEPROM.
|
||||
**/
|
||||
s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 checksum = 0;
|
||||
u16 i, nvm_data;
|
||||
|
||||
DEBUGFUNC("e1000_update_nvm_checksum");
|
||||
|
||||
for (i = 0; i < NVM_CHECKSUM_REG; i++) {
|
||||
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("NVM Read Error while updating checksum.\n");
|
||||
goto out;
|
||||
}
|
||||
checksum += nvm_data;
|
||||
}
|
||||
checksum = (u16) NVM_SUM - checksum;
|
||||
ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
|
||||
if (ret_val)
|
||||
DEBUGOUT("NVM Write Error while updating checksum.\n");
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_reload_nvm_generic - Reloads EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
|
||||
* extended control register.
|
||||
**/
|
||||
static void e1000_reload_nvm_generic(struct e1000_hw *hw)
|
||||
{
|
||||
u32 ctrl_ext;
|
||||
|
||||
DEBUGFUNC("e1000_reload_nvm_generic");
|
||||
|
||||
usec_delay(10);
|
||||
ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
|
||||
ctrl_ext |= E1000_CTRL_EXT_EE_RST;
|
||||
E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#ifndef _E1000_NVM_H_
|
||||
#define _E1000_NVM_H_
|
||||
|
||||
void e1000_init_nvm_ops_generic(struct e1000_hw *hw);
|
||||
s32 e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c);
|
||||
void e1000_null_nvm_generic(struct e1000_hw *hw);
|
||||
s32 e1000_null_led_default(struct e1000_hw *hw, u16 *data);
|
||||
s32 e1000_null_write_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c);
|
||||
s32 e1000_acquire_nvm_generic(struct e1000_hw *hw);
|
||||
|
||||
s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg);
|
||||
s32 e1000_read_mac_addr_generic(struct e1000_hw *hw);
|
||||
s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num);
|
||||
s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
|
||||
s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset,
|
||||
u16 words, u16 *data);
|
||||
s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words,
|
||||
u16 *data);
|
||||
s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data);
|
||||
s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw);
|
||||
s32 e1000_write_nvm_eewr(struct e1000_hw *hw, u16 offset,
|
||||
u16 words, u16 *data);
|
||||
s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset,
|
||||
u16 words, u16 *data);
|
||||
s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words,
|
||||
u16 *data);
|
||||
s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw);
|
||||
void e1000_stop_nvm(struct e1000_hw *hw);
|
||||
void e1000_release_nvm_generic(struct e1000_hw *hw);
|
||||
|
||||
#define E1000_STM_OPCODE 0xDB00
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2006 Intel Corporation.
|
||||
Copyright(c) 1999 - 2008 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,
|
||||
@@ -26,118 +26,93 @@
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/* glue for the OS independent part of e1000
|
||||
/* glue for the OS-dependent part of e1000
|
||||
* includes register access macros
|
||||
*/
|
||||
|
||||
#ifndef _E1000_OSDEP_H_
|
||||
#define _E1000_OSDEP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <gpxe/io.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <byteswap.h>
|
||||
#include <gpxe/pci.h>
|
||||
#include <gpxe/if_ether.h>
|
||||
#include <gpxe/ethernet.h>
|
||||
#include <gpxe/iobuf.h>
|
||||
#include <gpxe/netdevice.h>
|
||||
#define u8 unsigned char
|
||||
#define bool boolean_t
|
||||
#define dma_addr_t unsigned long
|
||||
#define __le16 uint16_t
|
||||
#define __le32 uint32_t
|
||||
#define __le64 uint64_t
|
||||
|
||||
#define __iomem
|
||||
|
||||
#define ETH_FCS_LEN 4
|
||||
|
||||
typedef int spinlock_t;
|
||||
typedef enum {
|
||||
#undef FALSE
|
||||
FALSE = 0,
|
||||
#undef TRUE
|
||||
TRUE = 1
|
||||
false = 0,
|
||||
true = 1
|
||||
} boolean_t;
|
||||
|
||||
/* Debugging #defines */
|
||||
#define usec_delay(x) udelay(x)
|
||||
#define msec_delay(x) mdelay(x)
|
||||
#define msec_delay_irq(x) mdelay(x)
|
||||
|
||||
#define PCI_COMMAND_REGISTER PCI_COMMAND
|
||||
#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE
|
||||
#define ETH_ADDR_LEN ETH_ALEN
|
||||
|
||||
#if 1
|
||||
#define DEBUGFUNC(F) DBG(F "\n")
|
||||
#else
|
||||
#define DEBUGFUNC(F)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define DEBUGOUT(S) DBG(S)
|
||||
#define DEBUGOUT1(S, A...) DBG(S, A)
|
||||
#else
|
||||
#define DEBUGOUT(S)
|
||||
#define DEBUGOUT1(S, A...)
|
||||
#endif
|
||||
|
||||
#define DEBUGOUT2 DEBUGOUT1
|
||||
#define DEBUGOUT3 DEBUGOUT1
|
||||
#define DEBUGOUT7 DEBUGOUT1
|
||||
#define DEBUGOUT3 DEBUGOUT2
|
||||
#define DEBUGOUT7 DEBUGOUT3
|
||||
|
||||
#define E1000_REGISTER(a, reg) (((a)->mac.type >= e1000_82543) \
|
||||
? reg \
|
||||
: e1000_translate_register_82542(reg))
|
||||
|
||||
#define E1000_WRITE_REG(a, reg, value) \
|
||||
writel((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)))
|
||||
writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg)))
|
||||
|
||||
#define E1000_READ_REG(a, reg) \
|
||||
readl((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg))
|
||||
#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + E1000_REGISTER(a, reg)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \
|
||||
writel((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2)))
|
||||
writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) \
|
||||
readl((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2))
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||
readl((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) \
|
||||
writew((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1)))
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||
writew((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 1))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) \
|
||||
readw((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1))
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||
readw((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 1)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) \
|
||||
writeb((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset)))
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||
writeb((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + (offset))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) \
|
||||
readb((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset))
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||
readb((a)->hw_addr + E1000_REGISTER(a, reg) + (offset)))
|
||||
|
||||
#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS)
|
||||
#define E1000_WRITE_REG_IO(a, reg, offset) do { \
|
||||
outl(reg, ((a)->io_base)); \
|
||||
outl(offset, ((a)->io_base + 4)); } while(0)
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) \
|
||||
writel((value), ((a)->flash_address + reg))
|
||||
#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS)
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG(a, reg) \
|
||||
readl((a)->flash_address + reg)
|
||||
#define E1000_WRITE_FLASH_REG(a, reg, value) ( \
|
||||
writel((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) \
|
||||
writew((value), ((a)->flash_address + reg))
|
||||
#define E1000_WRITE_FLASH_REG16(a, reg, value) ( \
|
||||
writew((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG16(a, reg) \
|
||||
readw((a)->flash_address + reg)
|
||||
#define E1000_READ_FLASH_REG(a, reg) (readl((a)->flash_address + reg))
|
||||
|
||||
#define msleep(n) mdelay(n)
|
||||
#define E1000_READ_FLASH_REG16(a, reg) (readw((a)->flash_address + reg))
|
||||
|
||||
#endif /* _E1000_OSDEP_H_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* c-indent-level: 8
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,171 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#ifndef _E1000_PHY_H_
|
||||
#define _E1000_PHY_H_
|
||||
|
||||
void e1000_init_phy_ops_generic(struct e1000_hw *hw);
|
||||
s32 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
void e1000_null_phy_generic(struct e1000_hw *hw);
|
||||
s32 e1000_null_lplu_state(struct e1000_hw *hw, bool active);
|
||||
s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 e1000_check_downshift_generic(struct e1000_hw *hw);
|
||||
s32 e1000_check_polarity_m88(struct e1000_hw *hw);
|
||||
s32 e1000_check_polarity_igp(struct e1000_hw *hw);
|
||||
s32 e1000_check_polarity_ife(struct e1000_hw *hw);
|
||||
s32 e1000_check_reset_block_generic(struct e1000_hw *hw);
|
||||
s32 e1000_copper_link_autoneg(struct e1000_hw *hw);
|
||||
s32 e1000_copper_link_setup_igp(struct e1000_hw *hw);
|
||||
s32 e1000_copper_link_setup_m88(struct e1000_hw *hw);
|
||||
#if 0
|
||||
s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw);
|
||||
s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw);
|
||||
s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw);
|
||||
#endif
|
||||
#if 0
|
||||
s32 e1000_get_cable_length_m88(struct e1000_hw *hw);
|
||||
s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw);
|
||||
#endif
|
||||
s32 e1000_get_cfg_done_generic(struct e1000_hw *hw);
|
||||
s32 e1000_get_phy_id(struct e1000_hw *hw);
|
||||
s32 e1000_get_phy_info_igp(struct e1000_hw *hw);
|
||||
s32 e1000_get_phy_info_m88(struct e1000_hw *hw);
|
||||
s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw);
|
||||
#if 0
|
||||
void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl);
|
||||
#endif
|
||||
s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw);
|
||||
s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw);
|
||||
s32 e1000_phy_setup_autoneg(struct e1000_hw *hw);
|
||||
s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active);
|
||||
s32 e1000_setup_copper_link_generic(struct e1000_hw *hw);
|
||||
s32 e1000_wait_autoneg_generic(struct e1000_hw *hw);
|
||||
s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
|
||||
s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
|
||||
u32 usec_interval, bool *success);
|
||||
s32 e1000_phy_init_script_igp3(struct e1000_hw *hw);
|
||||
enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id);
|
||||
s32 e1000_determine_phy_address(struct e1000_hw *hw);
|
||||
void e1000_power_up_phy_copper(struct e1000_hw *hw);
|
||||
void e1000_power_down_phy_copper(struct e1000_hw *hw);
|
||||
s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
|
||||
#define E1000_MAX_PHY_ADDR 4
|
||||
|
||||
/* IGP01E1000 Specific Registers */
|
||||
#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */
|
||||
#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */
|
||||
#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */
|
||||
#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */
|
||||
#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO */
|
||||
#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality */
|
||||
#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */
|
||||
#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */
|
||||
#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */
|
||||
#define IGP_PAGE_SHIFT 5
|
||||
#define PHY_REG_MASK 0x1F
|
||||
|
||||
#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4
|
||||
#define IGP01E1000_PHY_POLARITY_MASK 0x0078
|
||||
|
||||
#define IGP01E1000_PSCR_AUTO_MDIX 0x1000
|
||||
#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */
|
||||
|
||||
#define IGP01E1000_PSCFR_SMART_SPEED 0x0080
|
||||
|
||||
/* Enable flexible speed on link-up */
|
||||
#define IGP01E1000_GMII_FLEX_SPD 0x0010
|
||||
#define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */
|
||||
|
||||
#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */
|
||||
#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */
|
||||
#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */
|
||||
|
||||
#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000
|
||||
|
||||
#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002
|
||||
#define IGP01E1000_PSSR_MDIX 0x0800
|
||||
#define IGP01E1000_PSSR_SPEED_MASK 0xC000
|
||||
#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000
|
||||
|
||||
#define IGP02E1000_PHY_CHANNEL_NUM 4
|
||||
#define IGP02E1000_PHY_AGC_A 0x11B1
|
||||
#define IGP02E1000_PHY_AGC_B 0x12B1
|
||||
#define IGP02E1000_PHY_AGC_C 0x14B1
|
||||
#define IGP02E1000_PHY_AGC_D 0x18B1
|
||||
|
||||
#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */
|
||||
#define IGP02E1000_AGC_LENGTH_MASK 0x7F
|
||||
#define IGP02E1000_AGC_RANGE 15
|
||||
|
||||
#define IGP03E1000_PHY_MISC_CTRL 0x1B
|
||||
#define IGP03E1000_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Manually Set Duplex */
|
||||
|
||||
#define E1000_CABLE_LENGTH_UNDEFINED 0xFF
|
||||
|
||||
#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000
|
||||
#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16
|
||||
#define E1000_KMRNCTRLSTA_REN 0x00200000
|
||||
#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */
|
||||
#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */
|
||||
#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
|
||||
#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
|
||||
|
||||
#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
|
||||
#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */
|
||||
#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Control */
|
||||
#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */
|
||||
|
||||
/* IFE PHY Extended Status Control */
|
||||
#define IFE_PESC_POLARITY_REVERSED 0x0100
|
||||
|
||||
/* IFE PHY Special Control */
|
||||
#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010
|
||||
#define IFE_PSC_FORCE_POLARITY 0x0020
|
||||
#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100
|
||||
|
||||
/* IFE PHY Special Control and LED Control */
|
||||
#define IFE_PSCL_PROBE_MODE 0x0020
|
||||
#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */
|
||||
#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */
|
||||
|
||||
/* IFE PHY MDIX Control */
|
||||
#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */
|
||||
#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */
|
||||
#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto MDI/MDI-X, 0=disable */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,329 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel PRO/1000 Linux driver
|
||||
Copyright(c) 1999 - 2008 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#ifndef _E1000_REGS_H_
|
||||
#define _E1000_REGS_H_
|
||||
|
||||
#define E1000_CTRL 0x00000 /* Device Control - RW */
|
||||
#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */
|
||||
#define E1000_STATUS 0x00008 /* Device Status - RO */
|
||||
#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
|
||||
#define E1000_EERD 0x00014 /* EEPROM Read - RW */
|
||||
#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
|
||||
#define E1000_FLA 0x0001C /* Flash Access - RW */
|
||||
#define E1000_MDIC 0x00020 /* MDI Control - RW */
|
||||
#define E1000_SCTL 0x00024 /* SerDes Control - RW */
|
||||
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
|
||||
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
|
||||
#define E1000_FEXT 0x0002C /* Future Extended - RW */
|
||||
#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */
|
||||
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
|
||||
#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
|
||||
#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
|
||||
#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */
|
||||
#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
|
||||
#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
|
||||
#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
|
||||
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
|
||||
#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
|
||||
#define E1000_RCTL 0x00100 /* Rx Control - RW */
|
||||
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
|
||||
#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */
|
||||
#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */
|
||||
#define E1000_TCTL 0x00400 /* Tx Control - RW */
|
||||
#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */
|
||||
#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */
|
||||
#define E1000_TBT 0x00448 /* Tx Burst Timer - RW */
|
||||
#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
|
||||
#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
|
||||
#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
|
||||
#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
|
||||
#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
|
||||
#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
|
||||
#define E1000_PBS 0x01008 /* Packet Buffer Size */
|
||||
#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
|
||||
#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
|
||||
#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
|
||||
#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */
|
||||
#define E1000_FLSWCTL 0x01030 /* FLASH control register */
|
||||
#define E1000_FLSWDATA 0x01034 /* FLASH data register */
|
||||
#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */
|
||||
#define E1000_FLOP 0x0103C /* FLASH Opcode Register */
|
||||
#define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */
|
||||
#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */
|
||||
#define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */
|
||||
#define E1000_SWDSTS 0x01044 /* SW Device Status - RW */
|
||||
#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */
|
||||
#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */
|
||||
#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
|
||||
#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
|
||||
#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
|
||||
#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n)))
|
||||
#define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */
|
||||
#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */
|
||||
/* Split and Replication Rx Control - RW */
|
||||
#define E1000_RDPUMB 0x025CC /* DMA Rx Descriptor uC Mailbox - RW */
|
||||
#define E1000_RDPUAD 0x025D0 /* DMA Rx Descriptor uC Addr Command - RW */
|
||||
#define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */
|
||||
#define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */
|
||||
#define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */
|
||||
#define E1000_RXCTL(_n) (0x0C014 + (0x40 * (_n)))
|
||||
#define E1000_RQDPC(_n) (0x0C030 + (0x40 * (_n)))
|
||||
#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */
|
||||
#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */
|
||||
/*
|
||||
* Convenience macros
|
||||
*
|
||||
* Note: "_n" is the queue number of the register to be written to.
|
||||
*
|
||||
* Example usage:
|
||||
* E1000_RDBAL_REG(current_rx_queue)
|
||||
*/
|
||||
#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
|
||||
(0x0C000 + ((_n) * 0x40)))
|
||||
#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
|
||||
(0x0C004 + ((_n) * 0x40)))
|
||||
#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
|
||||
(0x0C008 + ((_n) * 0x40)))
|
||||
#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
|
||||
(0x0C00C + ((_n) * 0x40)))
|
||||
#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
|
||||
(0x0C010 + ((_n) * 0x40)))
|
||||
#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
|
||||
(0x0C018 + ((_n) * 0x40)))
|
||||
#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \
|
||||
(0x0C028 + ((_n) * 0x40)))
|
||||
#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
|
||||
(0x0E000 + ((_n) * 0x40)))
|
||||
#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
|
||||
(0x0E004 + ((_n) * 0x40)))
|
||||
#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
|
||||
(0x0E008 + ((_n) * 0x40)))
|
||||
#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
|
||||
(0x0E010 + ((_n) * 0x40)))
|
||||
#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
|
||||
(0x0E018 + ((_n) * 0x40)))
|
||||
#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
|
||||
(0x0E028 + ((_n) * 0x40)))
|
||||
#define E1000_TARC(_n) (0x03840 + (_n << 8))
|
||||
#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8))
|
||||
#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8))
|
||||
#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \
|
||||
(0x0E038 + ((_n) * 0x40)))
|
||||
#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \
|
||||
(0x0E03C + ((_n) * 0x40)))
|
||||
#define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */
|
||||
#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
|
||||
#define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */
|
||||
#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */
|
||||
#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4))
|
||||
#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
|
||||
(0x054E0 + ((_i - 16) * 8)))
|
||||
#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
|
||||
(0x054E4 + ((_i - 16) * 8)))
|
||||
#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
|
||||
#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
|
||||
#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
|
||||
#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8))
|
||||
#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8))
|
||||
#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8))
|
||||
#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */
|
||||
#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */
|
||||
#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */
|
||||
#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */
|
||||
#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */
|
||||
#define E1000_TDPUMB 0x0357C /* DMA Tx Descriptor uC Mail Box - RW */
|
||||
#define E1000_TDPUAD 0x03580 /* DMA Tx Descriptor uC Addr Command - RW */
|
||||
#define E1000_TDPUWD 0x03584 /* DMA Tx Descriptor uC Data Write - RW */
|
||||
#define E1000_TDPURD 0x03588 /* DMA Tx Descriptor uC Data Read - RW */
|
||||
#define E1000_TDPUCTL 0x0358C /* DMA Tx Descriptor uC Control - RW */
|
||||
#define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */
|
||||
#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */
|
||||
#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */
|
||||
#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
|
||||
#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
|
||||
#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
|
||||
#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
|
||||
#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */
|
||||
#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */
|
||||
#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */
|
||||
#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */
|
||||
#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */
|
||||
#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */
|
||||
#define E1000_COLC 0x04028 /* Collision Count - R/clr */
|
||||
#define E1000_DC 0x04030 /* Defer Count - R/clr */
|
||||
#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */
|
||||
#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
|
||||
#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
|
||||
#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
|
||||
#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */
|
||||
#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */
|
||||
#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */
|
||||
#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */
|
||||
#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */
|
||||
#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */
|
||||
#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */
|
||||
#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */
|
||||
#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */
|
||||
#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */
|
||||
#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */
|
||||
#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */
|
||||
#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */
|
||||
#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */
|
||||
#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */
|
||||
#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */
|
||||
#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */
|
||||
#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */
|
||||
#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */
|
||||
#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */
|
||||
#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */
|
||||
#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */
|
||||
#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */
|
||||
#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */
|
||||
#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */
|
||||
#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
|
||||
#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */
|
||||
#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */
|
||||
#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */
|
||||
#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */
|
||||
#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */
|
||||
#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */
|
||||
#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */
|
||||
#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */
|
||||
#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */
|
||||
#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */
|
||||
#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */
|
||||
#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */
|
||||
#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */
|
||||
#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */
|
||||
#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */
|
||||
#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */
|
||||
#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */
|
||||
#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
|
||||
#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */
|
||||
#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */
|
||||
#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */
|
||||
#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */
|
||||
#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
|
||||
#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */
|
||||
#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */
|
||||
#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
|
||||
|
||||
#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */
|
||||
#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */
|
||||
#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */
|
||||
#define E1000_CBTMPC 0x0402C /* Circuit Breaker Tx Packet Count */
|
||||
#define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */
|
||||
#define E1000_CBRDPC 0x04044 /* Circuit Breaker Rx Dropped Count */
|
||||
#define E1000_CBRMPC 0x040FC /* Circuit Breaker Rx Packet Count */
|
||||
#define E1000_RPTHC 0x04104 /* Rx Packets To Host */
|
||||
#define E1000_HGPTC 0x04118 /* Host Good Packets Tx Count */
|
||||
#define E1000_HTCBDPC 0x04124 /* Host Tx Circuit Breaker Dropped Count */
|
||||
#define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */
|
||||
#define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */
|
||||
#define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
|
||||
#define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
|
||||
#define E1000_LENERRS 0x04138 /* Length Errors Count */
|
||||
#define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */
|
||||
#define E1000_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */
|
||||
#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */
|
||||
#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */
|
||||
#define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */
|
||||
#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Page - RW */
|
||||
#define E1000_1GSTAT_RCV 0x04228 /* 1GSTAT Code Violation Packet Count - RW */
|
||||
#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */
|
||||
#define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */
|
||||
#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
|
||||
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
|
||||
#define E1000_RA 0x05400 /* Receive Address - RW Array */
|
||||
#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
|
||||
#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */
|
||||
#define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */
|
||||
#define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */
|
||||
#define E1000_WUC 0x05800 /* Wakeup Control - RW */
|
||||
#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */
|
||||
#define E1000_WUS 0x05810 /* Wakeup Status - RO */
|
||||
#define E1000_MANC 0x05820 /* Management Control - RW */
|
||||
#define E1000_IPAV 0x05838 /* IP Address Valid - RW */
|
||||
#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */
|
||||
#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */
|
||||
#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
|
||||
#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */
|
||||
#define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */
|
||||
#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
|
||||
#define E1000_HOST_IF 0x08800 /* Host Interface */
|
||||
#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
|
||||
#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
|
||||
|
||||
#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */
|
||||
#define E1000_MDPHYA 0x0003C /* PHY address - RW */
|
||||
#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */
|
||||
#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
|
||||
#define E1000_CCMCTL 0x05B48 /* CCM Control Register */
|
||||
#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
|
||||
#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
|
||||
#define E1000_GCR 0x05B00 /* PCI-Ex Control */
|
||||
#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */
|
||||
#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
|
||||
#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
|
||||
#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
|
||||
#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */
|
||||
#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
|
||||
#define E1000_SWSM 0x05B50 /* SW Semaphore */
|
||||
#define E1000_FWSM 0x05B54 /* FW Semaphore */
|
||||
#define E1000_SWSM2 0x05B58 /* Driver-only SW semaphore (not used by BOOT agents) */
|
||||
#define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */
|
||||
#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */
|
||||
#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
|
||||
#define E1000_HICR 0x08F00 /* Host Interface Control */
|
||||
|
||||
/* RSS registers */
|
||||
#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
|
||||
#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
|
||||
#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
|
||||
#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate Interrupt Ext*/
|
||||
#define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt Rx VLAN Priority - RW */
|
||||
#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Allocation Register
|
||||
* (_i) - RW */
|
||||
#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) /* MSI-X Table entry addr
|
||||
* low reg - RW */
|
||||
#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) /* MSI-X Table entry addr
|
||||
* upper reg - RW */
|
||||
#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) /* MSI-X Table entry
|
||||
* message reg - RW */
|
||||
#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* MSI-X Table entry
|
||||
* vector ctrl reg - RW */
|
||||
#define E1000_MSIXPBA 0x0E000 /* MSI-X Pending bit array */
|
||||
#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */
|
||||
#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */
|
||||
#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
|
||||
#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
|
||||
|
||||
#endif
|
||||
@@ -104,8 +104,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define ERRFILE_via_velocity ( ERRFILE_DRIVER | 0x00450000 )
|
||||
#define ERRFILE_w89c840 ( ERRFILE_DRIVER | 0x00460000 )
|
||||
#define ERRFILE_ipoib ( ERRFILE_DRIVER | 0x00470000 )
|
||||
#define ERRFILE_e1000 ( ERRFILE_DRIVER | 0x00480000 )
|
||||
#define ERRFILE_e1000_hw ( ERRFILE_DRIVER | 0x00490000 )
|
||||
#define ERRFILE_e1000_main ( ERRFILE_DRIVER | 0x00480000 )
|
||||
#define ERRFILE_mtnic ( ERRFILE_DRIVER | 0x004a0000 )
|
||||
#define ERRFILE_phantom ( ERRFILE_DRIVER | 0x004b0000 )
|
||||
#define ERRFILE_ne2k_isa ( ERRFILE_DRIVER | 0x004c0000 )
|
||||
|
||||
Reference in New Issue
Block a user