#define E1000_MAX_82544_RXD 4096
/* 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_2048 2048
#define E1000_RXBUFFER_4096 4096
#define E1000_RXBUFFER_8192 8192
#define E1000_MASTER_SLAVE e1000_ms_hw_default
#endif
+#define E1000_MNG_VLAN_NONE -1
+/* Number of packet split data buffers (not including the header buffer) */
+#define PS_PAGE_BUFFERS MAX_PS_BUFFERS-1
+
/* only works for sizes that are powers of 2 */
#define E1000_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1)))
uint16_t next_to_watch;
};
+struct e1000_ps_page { struct page *ps_page[MAX_PS_BUFFERS]; };
+struct e1000_ps_page_dma { uint64_t ps_page_dma[MAX_PS_BUFFERS]; };
+
struct e1000_desc_ring {
/* pointer to the descriptor ring memory */
void *desc;
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;
};
#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]))
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
struct timer_list watchdog_timer;
struct timer_list phy_info_timer;
struct vlan_group *vlgrp;
+ uint16_t mng_vlan_id;
uint32_t bd_number;
uint32_t rx_buffer_len;
uint32_t part_num;
boolean_t detect_tx_hung;
/* RX */
+#ifdef CONFIG_E1000_NAPI
+ boolean_t (*clean_rx) (struct e1000_adapter *adapter, int *work_done,
+ int work_to_do);
+#else
+ boolean_t (*clean_rx) (struct e1000_adapter *adapter);
+#endif
+ void (*alloc_rx_buf) (struct e1000_adapter *adapter);
struct e1000_desc_ring rx_ring;
uint64_t hw_csum_err;
uint64_t hw_csum_good;
uint32_t rx_int_delay;
uint32_t rx_abs_int_delay;
boolean_t rx_csum;
+ boolean_t rx_ps;
uint32_t gorcl;
uint64_t gorcl_old;
+ uint16_t rx_ps_bsize0;
/* Interrupt Throttle Rate */
uint32_t itr;
static int32_t e1000_acquire_eeprom(struct e1000_hw *hw);
static void e1000_release_eeprom(struct e1000_hw *hw);
static void e1000_standby_eeprom(struct e1000_hw *hw);
-static int32_t e1000_id_led_init(struct e1000_hw * hw);
static int32_t e1000_set_vco_speed(struct e1000_hw *hw);
static int32_t e1000_polarity_reversal_workaround(struct e1000_hw *hw);
static int32_t e1000_set_phy_mode(struct e1000_hw *hw);
+static int32_t e1000_host_if_read_cookie(struct e1000_hw *hw, uint8_t *buffer);
+static uint8_t e1000_calculate_mng_checksum(char *buffer, uint32_t length);
/* IGP cable length table */
static const
100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120};
+static const
+uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
+ { 8, 13, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43,
+ 22, 24, 27, 30, 32, 35, 37, 40, 42, 44, 47, 49, 51, 54, 56, 58,
+ 32, 35, 38, 41, 44, 47, 50, 53, 55, 58, 61, 63, 66, 69, 71, 74,
+ 43, 47, 51, 54, 58, 61, 64, 67, 71, 74, 77, 80, 82, 85, 88, 90,
+ 57, 62, 66, 70, 74, 77, 81, 85, 88, 91, 94, 97, 100, 103, 106, 108,
+ 73, 78, 82, 87, 91, 95, 98, 102, 105, 109, 112, 114, 117, 119, 122, 124,
+ 91, 96, 101, 105, 109, 113, 116, 119, 122, 125, 127, 128, 128, 128, 128, 128,
+ 108, 113, 117, 121, 124, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128};
+
/******************************************************************************
* Set the phy type member in the hw struct.
{
DEBUGFUNC("e1000_set_phy_type");
+ if(hw->mac_type == e1000_undefined)
+ return -E1000_ERR_PHY_TYPE;
+
switch(hw->phy_id) {
case M88E1000_E_PHY_ID:
case M88E1000_I_PHY_ID:
case M88E1011_I_PHY_ID:
+ case M88E1111_I_PHY_ID:
hw->phy_type = e1000_phy_m88;
break;
case IGP01E1000_I_PHY_ID:
case E1000_DEV_ID_82546GB_FIBER:
case E1000_DEV_ID_82546GB_SERDES:
case E1000_DEV_ID_82546GB_PCIE:
+ case E1000_DEV_ID_82546GB_QUAD_COPPER:
hw->mac_type = e1000_82546_rev_3;
break;
case E1000_DEV_ID_82541EI:
case E1000_DEV_ID_82547GI:
hw->mac_type = e1000_82547_rev_2;
break;
+ case E1000_DEV_ID_82573E:
+ case E1000_DEV_ID_82573E_IAMT:
+ hw->mac_type = e1000_82573;
+ break;
default:
/* Should never have loaded on this device */
return -E1000_ERR_MAC_TYPE;
}
switch(hw->mac_type) {
+ case e1000_82573:
+ hw->eeprom_semaphore_present = TRUE;
+ /* fall through */
case e1000_82541:
case e1000_82547:
case e1000_82541_rev_2:
uint32_t icr;
uint32_t manc;
uint32_t led_ctrl;
+ uint32_t timeout;
+ uint32_t extcnf_ctrl;
+ int32_t ret_val;
DEBUGFUNC("e1000_reset_hw");
e1000_pci_clear_mwi(hw);
}
+ if(hw->bus_type == e1000_bus_type_pci_express) {
+ /* Prevent the PCI-E bus from sticking if there is no TLP connection
+ * on the last TLP read/write transaction when MAC is reset.
+ */
+ if(e1000_disable_pciex_master(hw) != E1000_SUCCESS) {
+ DEBUGOUT("PCI-E Master disable polling has failed.\n");
+ }
+ }
+
/* Clear interrupt mask to stop board from generating interrupts */
DEBUGOUT("Masking off all interrupts\n");
E1000_WRITE_REG(hw, IMC, 0xffffffff);
/* Must reset the PHY before resetting the MAC */
if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
- E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST));
+ E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST));
msec_delay(5);
}
+ /* Must acquire the MDIO ownership before MAC reset.
+ * Ownership defaults to firmware after a reset. */
+ if(hw->mac_type == e1000_82573) {
+ timeout = 10;
+
+ extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+ extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+
+ do {
+ E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
+ extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+
+ if(extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
+ break;
+ else
+ extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+
+ msec_delay(2);
+ timeout--;
+ } while(timeout);
+ }
+
/* Issue a global reset to the MAC. This will reset the chip's
* transmit, receive, DMA, and link units. It will not effect
* the current PCI configuration. The global reset bit is self-
/* Wait for EEPROM reload */
msec_delay(20);
break;
+ case e1000_82573:
+ udelay(10);
+ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH(hw);
+ /* fall through */
+ ret_val = e1000_get_auto_rd_done(hw);
+ if(ret_val)
+ /* We don't want to continue accessing MAC registers. */
+ return ret_val;
+ break;
default:
/* Wait for EEPROM reload (it happens automatically) */
msec_delay(5);
}
/* Disable HW ARPs on ASF enabled adapters */
- if(hw->mac_type >= e1000_82540) {
+ if(hw->mac_type >= e1000_82540 && hw->mac_type <= e1000_82547_rev_2) {
manc = E1000_READ_REG(hw, MANC);
manc &= ~(E1000_MANC_ARP_EN);
E1000_WRITE_REG(hw, MANC, manc);
uint16_t pcix_stat_hi_word;
uint16_t cmd_mmrbc;
uint16_t stat_mmrbc;
+ uint32_t mta_size;
+
DEBUGFUNC("e1000_init_hw");
/* Initialize Identification LED */
/* Disabling VLAN filtering. */
DEBUGOUT("Initializing the IEEE VLAN\n");
- E1000_WRITE_REG(hw, VET, 0);
-
+ if (hw->mac_type < e1000_82545_rev_3)
+ E1000_WRITE_REG(hw, VET, 0);
e1000_clear_vfta(hw);
/* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
/* Zero out the Multicast HASH table */
DEBUGOUT("Zeroing the MTA\n");
- for(i = 0; i < E1000_MC_TBL_SIZE; i++)
+ mta_size = E1000_MC_TBL_SIZE;
+ for(i = 0; i < mta_size; i++)
E1000_WRITE_REG_ARRAY(hw, 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.
+ * gives equal priority to transmits and receives. Valid only on
+ * 82542 and 82543 silicon.
*/
- if(hw->dma_fairness) {
+ if(hw->dma_fairness && hw->mac_type <= e1000_82543) {
ctrl = E1000_READ_REG(hw, CTRL);
E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR);
}
if(hw->mac_type > e1000_82544) {
ctrl = E1000_READ_REG(hw, TXDCTL);
ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
+ switch (hw->mac_type) {
+ default:
+ break;
+ case e1000_82573:
+ ctrl |= E1000_TXDCTL_COUNT_DESC;
+ break;
+ }
E1000_WRITE_REG(hw, TXDCTL, ctrl);
}
+ if (hw->mac_type == e1000_82573) {
+ e1000_enable_tx_pkt_filtering(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
* control setting, then the variable hw->fc will
* be initialized based on a value in the EEPROM.
*/
- if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data) < 0) {
+ if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data)) {
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW);
E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE);
+
E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time);
/* Set the flow control receive threshold registers. Normally,
}
/******************************************************************************
-* Detects which PHY is present and the speed and duplex
+* Make sure we have a valid PHY and change PHY mode before link setup.
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
static int32_t
-e1000_setup_copper_link(struct e1000_hw *hw)
+e1000_copper_link_preconfig(struct e1000_hw *hw)
{
uint32_t ctrl;
- uint32_t led_ctrl;
int32_t ret_val;
- uint16_t i;
uint16_t phy_data;
- DEBUGFUNC("e1000_setup_copper_link");
+ DEBUGFUNC("e1000_copper_link_preconfig");
ctrl = E1000_READ_REG(hw, CTRL);
/* With 82543, we need to force speed and duplex on the MAC equal to what
} else {
ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
E1000_WRITE_REG(hw, CTRL, ctrl);
- e1000_phy_hw_reset(hw);
+ ret_val = e1000_phy_hw_reset(hw);
+ if(ret_val)
+ return ret_val;
}
/* Make sure we have a valid PHY */
hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2)
hw->phy_reset_disable = FALSE;
- if(!hw->phy_reset_disable) {
- if (hw->phy_type == e1000_phy_igp) {
-
- ret_val = e1000_phy_reset(hw);
- if(ret_val) {
- DEBUGOUT("Error Resetting the PHY\n");
- return ret_val;
- }
-
- /* Wait 10ms for MAC to configure PHY from eeprom settings */
- msec_delay(15);
+ return E1000_SUCCESS;
+}
- /* Configure activity LED after PHY reset */
- led_ctrl = E1000_READ_REG(hw, LEDCTL);
- led_ctrl &= IGP_ACTIVITY_LED_MASK;
- led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
- E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
- /* disable lplu d3 during driver init */
- ret_val = e1000_set_d3_lplu_state(hw, FALSE);
- if(ret_val) {
- DEBUGOUT("Error Disabling LPLU D3\n");
- return ret_val;
- }
+/********************************************************************
+* Copper link setup for e1000_phy_igp series.
+*
+* hw - Struct containing variables accessed by shared code
+*********************************************************************/
+static int32_t
+e1000_copper_link_igp_setup(struct e1000_hw *hw)
+{
+ uint32_t led_ctrl;
+ int32_t ret_val;
+ uint16_t phy_data;
- /* Configure mdi-mdix settings */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
- &phy_data);
- if(ret_val)
- return ret_val;
+ DEBUGFUNC("e1000_copper_link_igp_setup");
- if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
- hw->dsp_config_state = e1000_dsp_config_disabled;
- /* Force MDI for earlier revs of the IGP PHY */
- phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX |
- IGP01E1000_PSCR_FORCE_MDI_MDIX);
- hw->mdix = 1;
+ if (hw->phy_reset_disable)
+ return E1000_SUCCESS;
+
+ ret_val = e1000_phy_reset(hw);
+ if (ret_val) {
+ DEBUGOUT("Error Resetting the PHY\n");
+ return ret_val;
+ }
- } else {
- hw->dsp_config_state = e1000_dsp_config_enabled;
- phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
-
- switch (hw->mdix) {
- case 1:
- phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
- break;
- case 2:
- phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
- break;
- case 0:
- default:
- phy_data |= IGP01E1000_PSCR_AUTO_MDIX;
- break;
- }
- }
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
- phy_data);
- if(ret_val)
- return ret_val;
+ /* Wait 10ms for MAC to configure PHY from eeprom settings */
+ msec_delay(15);
- /* set auto-master slave resolution settings */
- if(hw->autoneg) {
- e1000_ms_type phy_ms_setting = hw->master_slave;
+ /* Configure activity LED after PHY reset */
+ led_ctrl = E1000_READ_REG(hw, LEDCTL);
+ led_ctrl &= IGP_ACTIVITY_LED_MASK;
+ led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
+ E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
- if(hw->ffe_config_state == e1000_ffe_config_active)
- hw->ffe_config_state = e1000_ffe_config_enabled;
+ /* disable lplu d3 during driver init */
+ ret_val = e1000_set_d3_lplu_state(hw, FALSE);
+ if (ret_val) {
+ DEBUGOUT("Error Disabling LPLU D3\n");
+ return ret_val;
+ }
- if(hw->dsp_config_state == e1000_dsp_config_activated)
- hw->dsp_config_state = e1000_dsp_config_enabled;
+ /* disable lplu d0 during driver init */
+ ret_val = e1000_set_d0_lplu_state(hw, FALSE);
+ if (ret_val) {
+ DEBUGOUT("Error Disabling LPLU D0\n");
+ return ret_val;
+ }
+ /* Configure mdi-mdix settings */
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
- /* when autonegotiation advertisment is only 1000Mbps then we
- * should disable SmartSpeed and enable Auto MasterSlave
- * resolution as hardware default. */
- if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
- /* Disable SmartSpeed */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- &phy_data);
- if(ret_val)
- return ret_val;
- phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = e1000_write_phy_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- phy_data);
- if(ret_val)
- return ret_val;
- /* Set auto Master/Slave resolution process */
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
- if(ret_val)
- return ret_val;
- phy_data &= ~CR_1000T_MS_ENABLE;
- ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
- if(ret_val)
- return ret_val;
- }
+ if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
+ hw->dsp_config_state = e1000_dsp_config_disabled;
+ /* Force MDI for earlier revs of the IGP PHY */
+ phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | IGP01E1000_PSCR_FORCE_MDI_MDIX);
+ hw->mdix = 1;
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
- if(ret_val)
- return ret_val;
+ } else {
+ hw->dsp_config_state = e1000_dsp_config_enabled;
+ phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
- /* load defaults for future use */
- hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
- ((phy_data & CR_1000T_MS_VALUE) ?
- e1000_ms_force_master :
- e1000_ms_force_slave) :
- e1000_ms_auto;
-
- switch (phy_ms_setting) {
- case e1000_ms_force_master:
- phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
- break;
- case e1000_ms_force_slave:
- phy_data |= CR_1000T_MS_ENABLE;
- phy_data &= ~(CR_1000T_MS_VALUE);
- break;
- case e1000_ms_auto:
- phy_data &= ~CR_1000T_MS_ENABLE;
- default:
- break;
- }
- ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
- if(ret_val)
- return ret_val;
- }
- } else {
- /* Enable CRS on TX. This must be set for half-duplex operation. */
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
- &phy_data);
- if(ret_val)
- return ret_val;
+ switch (hw->mdix) {
+ case 1:
+ phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
+ break;
+ case 2:
+ phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
+ break;
+ case 0:
+ default:
+ phy_data |= IGP01E1000_PSCR_AUTO_MDIX;
+ break;
+ }
+ }
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
- phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+ /* set auto-master slave resolution settings */
+ if(hw->autoneg) {
+ e1000_ms_type phy_ms_setting = hw->master_slave;
- /* Options:
- * MDI/MDI-X = 0 (default)
- * 0 - Auto for all speeds
- * 1 - MDI mode
- * 2 - MDI-X mode
- * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
- */
- phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+ if(hw->ffe_config_state == e1000_ffe_config_active)
+ hw->ffe_config_state = e1000_ffe_config_enabled;
- switch (hw->mdix) {
- case 1:
- phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
- break;
- case 2:
- phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
- break;
- case 3:
- phy_data |= M88E1000_PSCR_AUTO_X_1000T;
- break;
- case 0:
- default:
- phy_data |= M88E1000_PSCR_AUTO_X_MODE;
- break;
- }
+ if(hw->dsp_config_state == e1000_dsp_config_activated)
+ hw->dsp_config_state = e1000_dsp_config_enabled;
- /* Options:
- * disable_polarity_correction = 0 (default)
- * Automatic Correction for Reversed Cable Polarity
- * 0 - Disabled
- * 1 - Enabled
- */
- phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
- if(hw->disable_polarity_correction == 1)
- phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
- phy_data);
+ /* when autonegotiation advertisment is only 1000Mbps then we
+ * should disable SmartSpeed and enable Auto MasterSlave
+ * resolution as hardware default. */
+ if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
+ /* Disable SmartSpeed */
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
if(ret_val)
return ret_val;
-
- /* Force TX_CLK in the Extended PHY Specific Control Register
- * to 25MHz clock.
- */
- ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
- &phy_data);
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1000_write_phy_reg(hw,
+ IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
if(ret_val)
return ret_val;
+ /* Set auto Master/Slave resolution process */
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
+ phy_data &= ~CR_1000T_MS_ENABLE;
+ ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
+ }
- phy_data |= M88E1000_EPSCR_TX_CLK_25;
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
- if (hw->phy_revision < M88E1011_I_REV_4) {
- /* Configure Master and Slave downshift values */
- phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
- M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
- phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
- M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
- ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
- phy_data);
- if(ret_val)
- return ret_val;
- }
+ /* load defaults for future use */
+ hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
+ ((phy_data & CR_1000T_MS_VALUE) ?
+ e1000_ms_force_master :
+ e1000_ms_force_slave) :
+ e1000_ms_auto;
- /* SW Reset the PHY so all changes take effect */
- ret_val = e1000_phy_reset(hw);
- if(ret_val) {
- DEBUGOUT("Error Resetting the PHY\n");
- return ret_val;
- }
+ switch (phy_ms_setting) {
+ case e1000_ms_force_master:
+ phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_force_slave:
+ phy_data |= CR_1000T_MS_ENABLE;
+ phy_data &= ~(CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_auto:
+ phy_data &= ~CR_1000T_MS_ENABLE;
+ default:
+ break;
+ }
+ ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
}
- /* Options:
- * autoneg = 1 (default)
- * PHY will advertise value(s) parsed from
- * autoneg_advertised and fc
- * autoneg = 0
- * PHY will be set to 10H, 10F, 100H, or 100F
- * depending on value parsed from forced_speed_duplex.
- */
+ return E1000_SUCCESS;
+}
- /* Is autoneg enabled? This is enabled by default or by software
- * override. If so, call e1000_phy_setup_autoneg routine to parse the
- * autoneg_advertised and fc options. If autoneg is NOT enabled, then
- * the user should have provided a speed/duplex override. If so, then
- * call e1000_phy_force_speed_duplex to parse and set this up.
- */
- if(hw->autoneg) {
- /* Perform some bounds checking on the hw->autoneg_advertised
- * parameter. If this variable is zero, then set it to the default.
- */
- hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
- /* If autoneg_advertised is zero, we assume it was not defaulted
- * by the calling code so we set to advertise full capability.
- */
- if(hw->autoneg_advertised == 0)
- hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+/********************************************************************
+* Copper link setup for e1000_phy_m88 series.
+*
+* hw - Struct containing variables accessed by shared code
+*********************************************************************/
+static int32_t
+e1000_copper_link_mgp_setup(struct e1000_hw *hw)
+{
+ int32_t ret_val;
+ uint16_t phy_data;
- DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
- ret_val = e1000_phy_setup_autoneg(hw);
- if(ret_val) {
- DEBUGOUT("Error Setting up Auto-Negotiation\n");
- return ret_val;
- }
- DEBUGOUT("Restarting Auto-Neg\n");
+ DEBUGFUNC("e1000_copper_link_mgp_setup");
- /* Restart auto-negotiation by setting the Auto Neg Enable bit and
- * the Auto Neg Restart bit in the PHY control register.
- */
- ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
- if(ret_val)
- return ret_val;
+ if(hw->phy_reset_disable)
+ return E1000_SUCCESS;
+
+ /* Enable CRS on TX. This must be set for half-duplex operation. */
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
- phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
- ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
- if(ret_val)
- return ret_val;
+ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
- /* Does the user want to wait for Auto-Neg to complete here, or
- * check at a later time (for example, callback routine).
- */
- if(hw->wait_autoneg_complete) {
- ret_val = e1000_wait_autoneg(hw);
- if(ret_val) {
- DEBUGOUT("Error while waiting for autoneg to complete\n");
- return ret_val;
- }
- }
- hw->get_link_status = TRUE;
- } else {
- DEBUGOUT("Forcing speed and duplex\n");
- ret_val = e1000_phy_force_speed_duplex(hw);
- if(ret_val) {
- DEBUGOUT("Error Forcing Speed and Duplex\n");
- return ret_val;
- }
- }
- } /* !hw->phy_reset_disable */
+ /* Options:
+ * MDI/MDI-X = 0 (default)
+ * 0 - Auto for all speeds
+ * 1 - MDI mode
+ * 2 - MDI-X mode
+ * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+ */
+ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
- /* Check link status. Wait up to 100 microseconds for link to become
- * valid.
+ switch (hw->mdix) {
+ case 1:
+ phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
+ break;
+ case 2:
+ phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
+ break;
+ case 3:
+ phy_data |= M88E1000_PSCR_AUTO_X_1000T;
+ break;
+ case 0:
+ default:
+ phy_data |= M88E1000_PSCR_AUTO_X_MODE;
+ break;
+ }
+
+ /* Options:
+ * disable_polarity_correction = 0 (default)
+ * Automatic Correction for Reversed Cable Polarity
+ * 0 - Disabled
+ * 1 - Enabled
*/
- for(i = 0; i < 10; i++) {
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
+ if(hw->disable_polarity_correction == 1)
+ phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
if(ret_val)
return ret_val;
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+
+ /* Force TX_CLK in the Extended PHY Specific Control Register
+ * to 25MHz clock.
+ */
+ ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ phy_data |= M88E1000_EPSCR_TX_CLK_25;
+
+ if (hw->phy_revision < M88E1011_I_REV_4) {
+ /* Configure Master and Slave downshift values */
+ phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
+ M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
+ phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
+ M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
+ ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
if(ret_val)
return ret_val;
+ }
- if(phy_data & MII_SR_LINK_STATUS) {
- /* We have link, so we need to finish the config process:
- * 1) Set up the MAC to the current PHY speed/duplex
- * if we are on 82543. If we
- * are on newer silicon, we only need to configure
- * collision distance in the Transmit Control Register.
- * 2) Set up flow control on the MAC to that established with
- * the link partner.
- */
- if(hw->mac_type >= e1000_82544) {
- e1000_config_collision_dist(hw);
- } else {
- ret_val = e1000_config_mac_to_phy(hw);
- if(ret_val) {
- DEBUGOUT("Error configuring MAC to PHY settings\n");
- return ret_val;
- }
- }
- ret_val = e1000_config_fc_after_link_up(hw);
- if(ret_val) {
- DEBUGOUT("Error Configuring Flow Control\n");
- return ret_val;
- }
- DEBUGOUT("Valid link established!!!\n");
-
- if(hw->phy_type == e1000_phy_igp) {
- ret_val = e1000_config_dsp_after_link_change(hw, TRUE);
- if(ret_val) {
- DEBUGOUT("Error Configuring DSP after link up\n");
- return ret_val;
- }
- }
- DEBUGOUT("Valid link established!!!\n");
- return E1000_SUCCESS;
- }
- udelay(10);
+ /* SW Reset the PHY so all changes take effect */
+ ret_val = e1000_phy_reset(hw);
+ if(ret_val) {
+ DEBUGOUT("Error Resetting the PHY\n");
+ return ret_val;
}
- DEBUGOUT("Unable to establish link!!!\n");
- return E1000_SUCCESS;
+ return E1000_SUCCESS;
}
-/******************************************************************************
-* Configures PHY autoneg and flow control advertisement settings
+/********************************************************************
+* Setup auto-negotiation and flow control advertisements,
+* and then perform auto-negotiation.
*
* hw - Struct containing variables accessed by shared code
-******************************************************************************/
-int32_t
-e1000_phy_setup_autoneg(struct e1000_hw *hw)
+*********************************************************************/
+static int32_t
+e1000_copper_link_autoneg(struct e1000_hw *hw)
{
int32_t ret_val;
- uint16_t mii_autoneg_adv_reg;
- uint16_t mii_1000t_ctrl_reg;
+ uint16_t phy_data;
- DEBUGFUNC("e1000_phy_setup_autoneg");
+ DEBUGFUNC("e1000_copper_link_autoneg");
- /* Read the MII Auto-Neg Advertisement Register (Address 4). */
- ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
+ /* Perform some bounds checking on the hw->autoneg_advertised
+ * parameter. If this variable is zero, then set it to the default.
+ */
+ hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
+
+ /* If autoneg_advertised is zero, we assume it was not defaulted
+ * by the calling code so we set to advertise full capability.
+ */
+ if(hw->autoneg_advertised == 0)
+ hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+
+ DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
+ ret_val = e1000_phy_setup_autoneg(hw);
+ if(ret_val) {
+ DEBUGOUT("Error Setting up Auto-Negotiation\n");
+ return ret_val;
+ }
+ DEBUGOUT("Restarting Auto-Neg\n");
+
+ /* Restart auto-negotiation by setting the Auto Neg Enable bit and
+ * the Auto Neg Restart bit in the PHY control register.
+ */
+ ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
if(ret_val)
return ret_val;
- /* Read the MII 1000Base-T Control Register (Address 9). */
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
+ phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
+ ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
if(ret_val)
return ret_val;
- /* Need to parse both autoneg_advertised and fc and set up
- * the appropriate PHY registers. First we will parse for
+ /* Does the user want to wait for Auto-Neg to complete here, or
+ * check at a later time (for example, callback routine).
+ */
+ if(hw->wait_autoneg_complete) {
+ ret_val = e1000_wait_autoneg(hw);
+ if(ret_val) {
+ DEBUGOUT("Error while waiting for autoneg to complete\n");
+ return ret_val;
+ }
+ }
+
+ hw->get_link_status = TRUE;
+
+ return E1000_SUCCESS;
+}
+
+
+/******************************************************************************
+* Config the MAC and the PHY after link is up.
+* 1) Set up the MAC to the current PHY speed/duplex
+* if we are on 82543. If we
+* are on newer silicon, we only need to configure
+* collision distance in the Transmit Control Register.
+* 2) Set up flow control on the MAC to that established with
+* the link partner.
+* 3) Config DSP to improve Gigabit link quality for some PHY revisions.
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+static int32_t
+e1000_copper_link_postconfig(struct e1000_hw *hw)
+{
+ int32_t ret_val;
+ DEBUGFUNC("e1000_copper_link_postconfig");
+
+ if(hw->mac_type >= e1000_82544) {
+ e1000_config_collision_dist(hw);
+ } else {
+ ret_val = e1000_config_mac_to_phy(hw);
+ if(ret_val) {
+ DEBUGOUT("Error configuring MAC to PHY settings\n");
+ return ret_val;
+ }
+ }
+ ret_val = e1000_config_fc_after_link_up(hw);
+ if(ret_val) {
+ DEBUGOUT("Error Configuring Flow Control\n");
+ return ret_val;
+ }
+
+ /* Config DSP to improve Giga link quality */
+ if(hw->phy_type == e1000_phy_igp) {
+ ret_val = e1000_config_dsp_after_link_change(hw, TRUE);
+ if(ret_val) {
+ DEBUGOUT("Error Configuring DSP after link up\n");
+ return ret_val;
+ }
+ }
+
+ return E1000_SUCCESS;
+}
+
+/******************************************************************************
+* Detects which PHY is present and setup the speed and duplex
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+static int32_t
+e1000_setup_copper_link(struct e1000_hw *hw)
+{
+ int32_t ret_val;
+ uint16_t i;
+ uint16_t phy_data;
+
+ DEBUGFUNC("e1000_setup_copper_link");
+
+ /* Check if it is a valid PHY and set PHY mode if necessary. */
+ ret_val = e1000_copper_link_preconfig(hw);
+ if(ret_val)
+ return ret_val;
+
+ if (hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_2) {
+ ret_val = e1000_copper_link_igp_setup(hw);
+ if(ret_val)
+ return ret_val;
+ } else if (hw->phy_type == e1000_phy_m88) {
+ ret_val = e1000_copper_link_mgp_setup(hw);
+ if(ret_val)
+ return ret_val;
+ }
+
+ if(hw->autoneg) {
+ /* Setup autoneg and flow control advertisement
+ * and perform autonegotiation */
+ ret_val = e1000_copper_link_autoneg(hw);
+ if(ret_val)
+ return ret_val;
+ } else {
+ /* PHY will be set to 10H, 10F, 100H,or 100F
+ * depending on value from forced_speed_duplex. */
+ DEBUGOUT("Forcing speed and duplex\n");
+ ret_val = e1000_phy_force_speed_duplex(hw);
+ if(ret_val) {
+ DEBUGOUT("Error Forcing Speed and Duplex\n");
+ return ret_val;
+ }
+ }
+
+ /* Check link status. Wait up to 100 microseconds for link to become
+ * valid.
+ */
+ for(i = 0; i < 10; i++) {
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+ if(ret_val)
+ return ret_val;
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ if(phy_data & MII_SR_LINK_STATUS) {
+ /* Config the MAC and PHY after link is up */
+ ret_val = e1000_copper_link_postconfig(hw);
+ if(ret_val)
+ return ret_val;
+
+ DEBUGOUT("Valid link established!!!\n");
+ return E1000_SUCCESS;
+ }
+ udelay(10);
+ }
+
+ DEBUGOUT("Unable to establish link!!!\n");
+ return E1000_SUCCESS;
+}
+
+/******************************************************************************
+* Configures PHY autoneg and flow control advertisement settings
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+int32_t
+e1000_phy_setup_autoneg(struct e1000_hw *hw)
+{
+ int32_t ret_val;
+ uint16_t mii_autoneg_adv_reg;
+ uint16_t mii_1000t_ctrl_reg;
+
+ DEBUGFUNC("e1000_phy_setup_autoneg");
+
+ /* Read the MII Auto-Neg Advertisement Register (Address 4). */
+ ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
+ if(ret_val)
+ return ret_val;
+
+ /* Read the MII 1000Base-T Control Register (Address 9). */
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
+ if(ret_val)
+ return ret_val;
+
+ /* Need to parse both autoneg_advertised and fc and set up
+ * the appropriate PHY registers. First we will parse for
* autoneg_advertised software override. Since we can advertise
* a plethora of combinations, we need to check each bit
* individually.
DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
- ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
+ ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
if(ret_val)
return ret_val;
DEBUGFUNC("e1000_config_mac_to_phy");
+ /* 82544 or newer MAC, Auto Speed Detection takes care of
+ * MAC speed/duplex configuration.*/
+ if (hw->mac_type >= e1000_82544)
+ return E1000_SUCCESS;
+
/* Read the Device Control Register and set the bits to Force Speed
* and Duplex.
*/
/* Set up duplex in the Device Control and Transmit Control
* registers depending on negotiated values.
*/
- if (hw->phy_type == e1000_phy_igp) {
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
- &phy_data);
- if(ret_val)
- return ret_val;
-
- if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD;
- else ctrl &= ~E1000_CTRL_FD;
-
- e1000_config_collision_dist(hw);
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+ if(ret_val)
+ return ret_val;
- /* Set up speed in the Device Control register depending on
- * negotiated values.
- */
- if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
- IGP01E1000_PSSR_SPEED_1000MBPS)
- ctrl |= E1000_CTRL_SPD_1000;
- else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
- IGP01E1000_PSSR_SPEED_100MBPS)
- ctrl |= E1000_CTRL_SPD_100;
- } else {
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
- &phy_data);
- if(ret_val)
- return ret_val;
+ if(phy_data & M88E1000_PSSR_DPLX)
+ ctrl |= E1000_CTRL_FD;
+ else
+ ctrl &= ~E1000_CTRL_FD;
- if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD;
- else ctrl &= ~E1000_CTRL_FD;
+ e1000_config_collision_dist(hw);
- e1000_config_collision_dist(hw);
+ /* Set up speed in the Device Control register depending on
+ * negotiated values.
+ */
+ if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
+ ctrl |= E1000_CTRL_SPD_1000;
+ else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
+ ctrl |= E1000_CTRL_SPD_100;
- /* Set up speed in the Device Control register depending on
- * negotiated values.
- */
- if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
- ctrl |= E1000_CTRL_SPD_1000;
- else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
- ctrl |= E1000_CTRL_SPD_100;
- }
/* Write the configured values back to the Device Control Reg. */
E1000_WRITE_REG(hw, CTRL, ctrl);
return E1000_SUCCESS;
DEBUGFUNC("e1000_read_phy_reg");
-
- if(hw->phy_type == e1000_phy_igp &&
+ if((hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_2) &&
(reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
(uint16_t)reg_addr);
DEBUGFUNC("e1000_write_phy_reg");
-
- if(hw->phy_type == e1000_phy_igp &&
+ if((hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_2) &&
(reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
(uint16_t)reg_addr);
return E1000_SUCCESS;
}
+
/******************************************************************************
* Returns the PHY to the power-on reset state
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-void
+int32_t
e1000_phy_hw_reset(struct e1000_hw *hw)
{
uint32_t ctrl, ctrl_ext;
uint32_t led_ctrl;
+ int32_t ret_val;
DEBUGFUNC("e1000_phy_hw_reset");
+ /* In the case of the phy reset being blocked, it's not an error, we
+ * simply return success without performing the reset. */
+ ret_val = e1000_check_phy_reset_block(hw);
+ if (ret_val)
+ return E1000_SUCCESS;
+
DEBUGOUT("Resetting Phy...\n");
if(hw->mac_type > e1000_82543) {
led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
}
+
+ /* Wait for FW to finish PHY configuration. */
+ ret_val = e1000_get_phy_cfg_done(hw);
+
+ return ret_val;
}
/******************************************************************************
DEBUGFUNC("e1000_phy_reset");
- if(hw->mac_type != e1000_82541_rev_2) {
+ /* In the case of the phy reset being blocked, it's not an error, we
+ * simply return success without performing the reset. */
+ ret_val = e1000_check_phy_reset_block(hw);
+ if (ret_val)
+ return E1000_SUCCESS;
+
+ switch (hw->mac_type) {
+ case e1000_82541_rev_2:
+ ret_val = e1000_phy_hw_reset(hw);
+ if(ret_val)
+ return ret_val;
+ break;
+ default:
ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
if(ret_val)
return ret_val;
return ret_val;
udelay(1);
- } else e1000_phy_hw_reset(hw);
+ break;
+ }
- if(hw->phy_type == e1000_phy_igp)
+ if(hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_igp_2)
e1000_phy_init_script(hw);
return E1000_SUCCESS;
case e1000_82547_rev_2:
if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
break;
+ case e1000_82573:
+ if(hw->phy_id == M88E1111_I_PHY_ID) match = TRUE;
+ break;
default:
DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
return -E1000_ERR_CONFIG;
/* The downshift status is checked only once, after link is established,
* and it stored in the hw->speed_downgraded parameter. */
- phy_info->downshift = hw->speed_downgraded;
+ phy_info->downshift = (e1000_downshift)hw->speed_downgraded;
/* IGP01E1000 does not need to support it. */
phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal;
if(ret_val)
return ret_val;
- /* transalte to old method */
+ /* Translate to old method */
average = (max_length + min_length) / 2;
if(average <= e1000_igp_cable_length_50)
/* The downshift status is checked only once, after link is established,
* and it stored in the hw->speed_downgraded parameter. */
- phy_info->downshift = hw->speed_downgraded;
+ phy_info->downshift = (e1000_downshift)hw->speed_downgraded;
ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if(ret_val)
return -E1000_ERR_CONFIG;
}
- if(hw->phy_type == e1000_phy_igp)
+ if(hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_2)
return e1000_phy_igp_get_info(hw, phy_info);
else
return e1000_phy_m88_get_info(hw, phy_info);
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void
+int32_t
e1000_init_eeprom_params(struct e1000_hw *hw)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
uint32_t eecd = E1000_READ_REG(hw, EECD);
+ int32_t ret_val = E1000_SUCCESS;
uint16_t eeprom_size;
DEBUGFUNC("e1000_init_eeprom_params");
eeprom->opcode_bits = 3;
eeprom->address_bits = 6;
eeprom->delay_usec = 50;
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
break;
case e1000_82540:
case e1000_82545:
eeprom->word_size = 64;
eeprom->address_bits = 6;
}
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
break;
case e1000_82541:
case e1000_82541_rev_2:
eeprom->address_bits = 6;
}
}
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
+ break;
+ case e1000_82573:
+ eeprom->type = e1000_eeprom_spi;
+ eeprom->opcode_bits = 8;
+ eeprom->delay_usec = 1;
+ if (eecd & E1000_EECD_ADDR_BITS) {
+ eeprom->page_size = 32;
+ eeprom->address_bits = 16;
+ } else {
+ eeprom->page_size = 8;
+ eeprom->address_bits = 8;
+ }
+ eeprom->use_eerd = TRUE;
+ eeprom->use_eewr = TRUE;
+ if(e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
+ eeprom->type = e1000_eeprom_flash;
+ eeprom->word_size = 2048;
+
+ /* Ensure that the Autonomous FLASH update bit is cleared due to
+ * Flash update issue on parts which use a FLASH for NVM. */
+ eecd &= ~E1000_EECD_AUPDEN;
+ E1000_WRITE_REG(hw, EECD, eecd);
+ }
break;
default:
break;
}
if (eeprom->type == e1000_eeprom_spi) {
- eeprom->word_size = 64;
- if (e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size) == 0) {
- eeprom_size &= EEPROM_SIZE_MASK;
-
- switch (eeprom_size) {
- case EEPROM_SIZE_16KB:
- eeprom->word_size = 8192;
- break;
- case EEPROM_SIZE_8KB:
- eeprom->word_size = 4096;
- break;
- case EEPROM_SIZE_4KB:
- eeprom->word_size = 2048;
- break;
- case EEPROM_SIZE_2KB:
- eeprom->word_size = 1024;
- break;
- case EEPROM_SIZE_1KB:
- eeprom->word_size = 512;
- break;
- case EEPROM_SIZE_512B:
- eeprom->word_size = 256;
- break;
- case EEPROM_SIZE_128B:
- default:
- eeprom->word_size = 64;
- break;
- }
+ /* eeprom_size will be an enum [0..8] that maps to eeprom sizes 128B to
+ * 32KB (incremented by powers of 2).
+ */
+ if(hw->mac_type <= e1000_82547_rev_2) {
+ /* Set to default value for initial eeprom read. */
+ eeprom->word_size = 64;
+ ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size);
+ if(ret_val)
+ return ret_val;
+ eeprom_size = (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT;
+ /* 256B eeprom size was not supported in earlier hardware, so we
+ * bump eeprom_size up one to ensure that "1" (which maps to 256B)
+ * is never the result used in the shifting logic below. */
+ if(eeprom_size)
+ eeprom_size++;
+ } else {
+ eeprom_size = (uint16_t)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+ E1000_EECD_SIZE_EX_SHIFT);
}
+
+ eeprom->word_size = 1 << (eeprom_size + EEPROM_WORD_SIZE_SHIFT);
}
+ return ret_val;
}
/******************************************************************************
DEBUGFUNC("e1000_acquire_eeprom");
+ if(e1000_get_hw_eeprom_semaphore(hw))
+ return -E1000_ERR_EEPROM;
+
eecd = E1000_READ_REG(hw, EECD);
+ if (hw->mac_type != e1000_82573) {
/* Request EEPROM Access */
if(hw->mac_type > e1000_82544) {
eecd |= E1000_EECD_REQ;
return -E1000_ERR_EEPROM;
}
}
+ }
/* Setup EEPROM for Read/Write */
eecd &= ~E1000_EECD_REQ;
E1000_WRITE_REG(hw, EECD, eecd);
}
+
+ e1000_put_hw_eeprom_semaphore(hw);
}
/******************************************************************************
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
uint32_t i = 0;
+ int32_t ret_val;
DEBUGFUNC("e1000_read_eeprom");
+
/* A check for invalid values: offset too large, too many words, and not
* enough words.
*/
return -E1000_ERR_EEPROM;
}
- /* Prepare the EEPROM for reading */
- if(e1000_acquire_eeprom(hw) != E1000_SUCCESS)
- return -E1000_ERR_EEPROM;
+ /* FLASH reads without acquiring the semaphore are safe in 82573-based
+ * controllers.
+ */
+ if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) ||
+ (hw->mac_type != e1000_82573)) {
+ /* Prepare the EEPROM for reading */
+ if(e1000_acquire_eeprom(hw) != E1000_SUCCESS)
+ return -E1000_ERR_EEPROM;
+ }
+
+ if(eeprom->use_eerd == TRUE) {
+ ret_val = e1000_read_eeprom_eerd(hw, offset, words, data);
+ if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) ||
+ (hw->mac_type != e1000_82573))
+ e1000_release_eeprom(hw);
+ return ret_val;
+ }
if(eeprom->type == e1000_eeprom_spi) {
uint16_t word_in;
}
/******************************************************************************
- * Verifies that the EEPROM has a valid checksum
+ * Reads a 16 bit word from the EEPROM using the EERD register.
*
* hw - Struct containing variables accessed by shared code
- *
- * Reads the first 64 16 bit words of the EEPROM and sums the values read.
- * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
- * valid.
+ * offset - offset of word in the EEPROM to read
+ * data - word read from the EEPROM
+ * words - number of words to read
*****************************************************************************/
int32_t
-e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+e1000_read_eeprom_eerd(struct e1000_hw *hw,
+ uint16_t offset,
+ uint16_t words,
+ uint16_t *data)
{
- uint16_t checksum = 0;
- uint16_t i, eeprom_data;
+ uint32_t i, eerd = 0;
+ int32_t error = 0;
- DEBUGFUNC("e1000_validate_eeprom_checksum");
+ for (i = 0; i < words; i++) {
+ eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) +
+ E1000_EEPROM_RW_REG_START;
- for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
- if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
- DEBUGOUT("EEPROM Read Error\n");
- return -E1000_ERR_EEPROM;
+ E1000_WRITE_REG(hw, EERD, eerd);
+ error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ);
+
+ if(error) {
+ break;
}
- checksum += eeprom_data;
- }
-
- if(checksum == (uint16_t) EEPROM_SUM)
- return E1000_SUCCESS;
- else {
- DEBUGOUT("EEPROM Checksum Invalid\n");
- return -E1000_ERR_EEPROM;
+ data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA);
+
}
+
+ return error;
}
/******************************************************************************
- * Calculates the EEPROM checksum and writes it to the EEPROM
+ * Writes a 16 bit word from the EEPROM using the EEWR register.
*
* hw - Struct containing variables accessed by shared code
- *
- * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
- * Writes the difference to word offset 63 of the EEPROM.
+ * offset - offset of word in the EEPROM to read
+ * data - word read from the EEPROM
+ * words - number of words to read
*****************************************************************************/
int32_t
-e1000_update_eeprom_checksum(struct e1000_hw *hw)
+e1000_write_eeprom_eewr(struct e1000_hw *hw,
+ uint16_t offset,
+ uint16_t words,
+ uint16_t *data)
{
- uint16_t checksum = 0;
- uint16_t i, eeprom_data;
+ uint32_t register_value = 0;
+ uint32_t i = 0;
+ int32_t error = 0;
- DEBUGFUNC("e1000_update_eeprom_checksum");
+ for (i = 0; i < words; i++) {
+ register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) |
+ ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) |
+ E1000_EEPROM_RW_REG_START;
- for(i = 0; i < EEPROM_CHECKSUM_REG; i++) {
- if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
- DEBUGOUT("EEPROM Read Error\n");
- return -E1000_ERR_EEPROM;
- }
- checksum += eeprom_data;
- }
- checksum = (uint16_t) EEPROM_SUM - checksum;
+ error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
+ if(error) {
+ break;
+ }
+
+ E1000_WRITE_REG(hw, EEWR, register_value);
+
+ error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
+
+ if(error) {
+ break;
+ }
+ }
+
+ return error;
+}
+
+/******************************************************************************
+ * Polls the status bit (bit 1) of the EERD to determine when the read is done.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+int32_t
+e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
+{
+ uint32_t attempts = 100000;
+ uint32_t i, reg = 0;
+ int32_t done = E1000_ERR_EEPROM;
+
+ for(i = 0; i < attempts; i++) {
+ if(eerd == E1000_EEPROM_POLL_READ)
+ reg = E1000_READ_REG(hw, EERD);
+ else
+ reg = E1000_READ_REG(hw, EEWR);
+
+ if(reg & E1000_EEPROM_RW_REG_DONE) {
+ done = E1000_SUCCESS;
+ break;
+ }
+ udelay(5);
+ }
+
+ return done;
+}
+
+/***************************************************************************
+* Description: Determines if the onboard NVM is FLASH or EEPROM.
+*
+* hw - Struct containing variables accessed by shared code
+****************************************************************************/
+boolean_t
+e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+{
+ uint32_t eecd = 0;
+
+ if(hw->mac_type == e1000_82573) {
+ eecd = E1000_READ_REG(hw, EECD);
+
+ /* Isolate bits 15 & 16 */
+ eecd = ((eecd >> 15) & 0x03);
+
+ /* If both bits are set, device is Flash type */
+ if(eecd == 0x03) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/******************************************************************************
+ * Verifies that the EEPROM has a valid checksum
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Reads the first 64 16 bit words of the EEPROM and sums the values read.
+ * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
+ * valid.
+ *****************************************************************************/
+int32_t
+e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+{
+ uint16_t checksum = 0;
+ uint16_t i, eeprom_data;
+
+ DEBUGFUNC("e1000_validate_eeprom_checksum");
+
+ if ((hw->mac_type == e1000_82573) &&
+ (e1000_is_onboard_nvm_eeprom(hw) == FALSE)) {
+ /* Check bit 4 of word 10h. If it is 0, firmware is done updating
+ * 10h-12h. Checksum may need to be fixed. */
+ e1000_read_eeprom(hw, 0x10, 1, &eeprom_data);
+ if ((eeprom_data & 0x10) == 0) {
+ /* Read 0x23 and check bit 15. This bit is a 1 when the checksum
+ * has already been fixed. If the checksum is still wrong and this
+ * bit is a 1, we need to return bad checksum. Otherwise, we need
+ * to set this bit to a 1 and update the checksum. */
+ e1000_read_eeprom(hw, 0x23, 1, &eeprom_data);
+ if ((eeprom_data & 0x8000) == 0) {
+ eeprom_data |= 0x8000;
+ e1000_write_eeprom(hw, 0x23, 1, &eeprom_data);
+ e1000_update_eeprom_checksum(hw);
+ }
+ }
+ }
+
+ for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
+ if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+ checksum += eeprom_data;
+ }
+
+ if(checksum == (uint16_t) EEPROM_SUM)
+ return E1000_SUCCESS;
+ else {
+ DEBUGOUT("EEPROM Checksum Invalid\n");
+ return -E1000_ERR_EEPROM;
+ }
+}
+
+/******************************************************************************
+ * Calculates the EEPROM checksum and writes it to the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
+ * Writes the difference to word offset 63 of the EEPROM.
+ *****************************************************************************/
+int32_t
+e1000_update_eeprom_checksum(struct e1000_hw *hw)
+{
+ uint16_t checksum = 0;
+ uint16_t i, eeprom_data;
+
+ DEBUGFUNC("e1000_update_eeprom_checksum");
+
+ for(i = 0; i < EEPROM_CHECKSUM_REG; i++) {
+ if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+ checksum += eeprom_data;
+ }
+ checksum = (uint16_t) EEPROM_SUM - checksum;
if(e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
DEBUGOUT("EEPROM Write Error\n");
return -E1000_ERR_EEPROM;
+ } else if (hw->eeprom.type == e1000_eeprom_flash) {
+ e1000_commit_shadow_ram(hw);
}
return E1000_SUCCESS;
}
return -E1000_ERR_EEPROM;
}
+ /* 82573 reads only through eerd */
+ if(eeprom->use_eewr == TRUE)
+ return e1000_write_eeprom_eewr(hw, offset, words, data);
+
/* Prepare the EEPROM for writing */
if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
return -E1000_ERR_EEPROM;
return E1000_SUCCESS;
}
+/******************************************************************************
+ * Flushes the cached eeprom to NVM. This is done by saving the modified values
+ * in the eeprom cache and the non modified values in the currently active bank
+ * to the new bank.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - offset of word in the EEPROM to read
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+int32_t
+e1000_commit_shadow_ram(struct e1000_hw *hw)
+{
+ uint32_t attempts = 100000;
+ uint32_t eecd = 0;
+ uint32_t flop = 0;
+ uint32_t i = 0;
+ int32_t error = E1000_SUCCESS;
+
+ /* The flop register will be used to determine if flash type is STM */
+ flop = E1000_READ_REG(hw, FLOP);
+
+ if (hw->mac_type == e1000_82573) {
+ for (i=0; i < attempts; i++) {
+ eecd = E1000_READ_REG(hw, EECD);
+ if ((eecd & E1000_EECD_FLUPD) == 0) {
+ break;
+ }
+ udelay(5);
+ }
+
+ if (i == attempts) {
+ return -E1000_ERR_EEPROM;
+ }
+
+ /* If STM opcode located in bits 15:8 of flop, reset firmware */
+ if ((flop & 0xFF00) == E1000_STM_OPCODE) {
+ E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET);
+ }
+
+ /* Perform the flash update */
+ E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD);
+
+ for (i=0; i < attempts; i++) {
+ eecd = E1000_READ_REG(hw, EECD);
+ if ((eecd & E1000_EECD_FLUPD) == 0) {
+ break;
+ }
+ udelay(5);
+ }
+
+ if (i == attempts) {
+ return -E1000_ERR_EEPROM;
+ }
+ }
+
+ return error;
+}
+
/******************************************************************************
* Reads the adapter's part number from the EEPROM
*
e1000_init_rx_addrs(struct e1000_hw *hw)
{
uint32_t i;
+ uint32_t rar_num;
DEBUGFUNC("e1000_init_rx_addrs");
e1000_rar_set(hw, hw->mac_addr, 0);
+ rar_num = E1000_RAR_ENTRIES;
/* Zero out the other 15 receive addresses. */
DEBUGOUT("Clearing RAR[1-15]\n");
- for(i = 1; i < E1000_RAR_ENTRIES; i++) {
+ for(i = 1; i < rar_num; i++) {
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
}
{
uint32_t hash_value;
uint32_t i;
-
+ uint32_t num_rar_entry;
+ uint32_t num_mta_entry;
+
DEBUGFUNC("e1000_mc_addr_list_update");
/* Set the new number of MC addresses that we are being requested to use. */
/* Clear RAR[1-15] */
DEBUGOUT(" Clearing RAR[1-15]\n");
- for(i = rar_used_count; i < E1000_RAR_ENTRIES; i++) {
+ num_rar_entry = E1000_RAR_ENTRIES;
+ for(i = rar_used_count; i < num_rar_entry; i++) {
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
}
/* Clear the MTA */
DEBUGOUT(" Clearing MTA\n");
- for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++) {
+ num_mta_entry = E1000_NUM_MTA_REGISTERS;
+ for(i = 0; i < num_mta_entry; i++) {
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
}
/* Place this multicast address in the RAR if there is room, *
* else put it in the MTA
*/
- if(rar_used_count < E1000_RAR_ENTRIES) {
+ if (rar_used_count < num_rar_entry) {
e1000_rar_set(hw,
mc_addr_list + (i * (ETH_LENGTH_OF_ADDRESS + pad)),
rar_used_count);
}
hash_value &= 0xFFF;
+
return hash_value;
}
e1000_clear_vfta(struct e1000_hw *hw)
{
uint32_t offset;
-
- for(offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++)
- E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
+ uint32_t vfta_value = 0;
+ uint32_t vfta_offset = 0;
+ uint32_t vfta_bit_in_reg = 0;
+
+ if (hw->mac_type == e1000_82573) {
+ if (hw->mng_cookie.vlan_id != 0) {
+ /* The VFTA is a 4096b bit-field, each identifying a single VLAN
+ * ID. The following operations determine which 32b entry
+ * (i.e. offset) into the array we want to set the VLAN ID
+ * (i.e. bit) of the manageability unit. */
+ vfta_offset = (hw->mng_cookie.vlan_id >>
+ E1000_VFTA_ENTRY_SHIFT) &
+ E1000_VFTA_ENTRY_MASK;
+ vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id &
+ E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
+ }
+ }
+ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
+ /* If the offset we want to clear is the same offset of the
+ * manageability VLAN ID, then clear all bits except that of the
+ * manageability unit */
+ vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
+ E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value);
+ }
}
-static int32_t
+int32_t
e1000_id_led_init(struct e1000_hw * hw)
{
uint32_t ledctl;
temp = E1000_READ_REG(hw, MGTPRC);
temp = E1000_READ_REG(hw, MGTPDC);
temp = E1000_READ_REG(hw, MGTPTC);
+
+ if(hw->mac_type <= e1000_82547_rev_2) return;
+
+ temp = E1000_READ_REG(hw, IAC);
+ temp = E1000_READ_REG(hw, ICRXOC);
+ temp = E1000_READ_REG(hw, ICRXPTC);
+ temp = E1000_READ_REG(hw, ICRXATC);
+ temp = E1000_READ_REG(hw, ICTXPTC);
+ temp = E1000_READ_REG(hw, ICTXATC);
+ temp = E1000_READ_REG(hw, ICTXQEC);
+ temp = E1000_READ_REG(hw, ICTXQMTC);
+ temp = E1000_READ_REG(hw, ICRXDMTC);
+
}
/******************************************************************************
hw->bus_speed = e1000_bus_speed_unknown;
hw->bus_width = e1000_bus_width_unknown;
break;
+ case e1000_82573:
+ hw->bus_type = e1000_bus_type_pci_express;
+ hw->bus_speed = e1000_bus_speed_2500;
+ hw->bus_width = e1000_bus_width_pciex_4;
+ break;
default:
status = E1000_READ_REG(hw, STATUS);
hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
/* Use old method for Phy older than IGP */
if(hw->phy_type == e1000_phy_m88) {
+
ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
&phy_data);
if(ret_val)
return ret_val;
*polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >>
M88E1000_PSSR_REV_POLARITY_SHIFT;
- } else if(hw->phy_type == e1000_phy_igp) {
+ } else if(hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_2) {
/* Read the Status register to check the speed */
ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
&phy_data);
DEBUGFUNC("e1000_check_downshift");
- if(hw->phy_type == e1000_phy_igp) {
+ if(hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_2) {
ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
&phy_data);
if(ret_val)
hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
M88E1000_PSSR_DOWNSHIFT_SHIFT;
}
+
return E1000_SUCCESS;
}
if(ret_val)
return ret_val;
- msec_delay(20);
+ msec_delay_irq(20);
ret_val = e1000_write_phy_reg(hw, 0x0000,
IGP01E1000_IEEE_FORCE_GIGA);
if(ret_val)
return ret_val;
- msec_delay(20);
+ msec_delay_irq(20);
/* Now enable the transmitter */
ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
if(ret_val)
return ret_val;
- msec_delay(20);
+ msec_delay_irq(20);
ret_val = e1000_write_phy_reg(hw, 0x0000,
IGP01E1000_IEEE_FORCE_GIGA);
if(ret_val)
return ret_val;
- msec_delay(20);
+ msec_delay_irq(20);
/* Now enable the transmitter */
ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
uint16_t phy_data;
DEBUGFUNC("e1000_set_d3_lplu_state");
- if(!((hw->mac_type == e1000_82541_rev_2) ||
- (hw->mac_type == e1000_82547_rev_2)))
+ if(hw->phy_type != e1000_phy_igp && hw->phy_type != e1000_phy_igp_2)
return E1000_SUCCESS;
/* During driver activity LPLU should not be used or it will attain link
* from the lowest speeds starting from 10Mbps. The capability is used for
* Dx transitions and states */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
- if(ret_val)
- return ret_val;
-
- if(!active) {
- phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+ if(hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) {
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
+ if(ret_val)
+ return ret_val;
+ } else {
+ ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
if(ret_val)
return ret_val;
+ }
+
+ if(!active) {
+ if(hw->mac_type == e1000_82541_rev_2 ||
+ hw->mac_type == e1000_82547_rev_2) {
+ phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+ if(ret_val)
+ return ret_val;
+ } else {
+ phy_data &= ~IGP02E1000_PM_D3_LPLU;
+ ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ }
/* LPLU and SmartSpeed are mutually exclusive. LPLU is used during
* Dx states where the power conservation is most important. During
(hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) ||
(hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) {
- phy_data |= IGP01E1000_GMII_FLEX_SPD;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+ if(hw->mac_type == e1000_82541_rev_2 ||
+ hw->mac_type == e1000_82547_rev_2) {
+ phy_data |= IGP01E1000_GMII_FLEX_SPD;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+ if(ret_val)
+ return ret_val;
+ } else {
+ phy_data |= IGP02E1000_PM_D3_LPLU;
+ ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ }
+
+ /* When LPLU is enabled we should disable SmartSpeed */
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data);
+ if(ret_val)
+ return ret_val;
+
+ }
+ return E1000_SUCCESS;
+}
+
+/*****************************************************************************
+ *
+ * This function sets the lplu d0 state according to the active flag. When
+ * activating lplu this function also disables smart speed and vise versa.
+ * lplu will not be activated unless the device autonegotiation advertisment
+ * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes.
+ * hw: Struct containing variables accessed by shared code
+ * active - true to enable lplu false to disable lplu.
+ *
+ * returns: - E1000_ERR_PHY if fail to read/write the PHY
+ * E1000_SUCCESS at any other case.
+ *
+ ****************************************************************************/
+
+int32_t
+e1000_set_d0_lplu_state(struct e1000_hw *hw,
+ boolean_t active)
+{
+ int32_t ret_val;
+ uint16_t phy_data;
+ DEBUGFUNC("e1000_set_d0_lplu_state");
+
+ if(hw->mac_type <= e1000_82547_rev_2)
+ return E1000_SUCCESS;
+
+ ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
if(ret_val)
return ret_val;
+ if (!active) {
+ phy_data &= ~IGP02E1000_PM_D0_LPLU;
+ ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during
+ * Dx states where the power conservation is most important. During
+ * driver activity we should enable SmartSpeed, so performance is
+ * maintained. */
+ if (hw->smart_speed == e1000_smart_speed_on) {
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if(ret_val)
+ return ret_val;
+ } else if (hw->smart_speed == e1000_smart_speed_off) {
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if(ret_val)
+ return ret_val;
+ }
+
+
+ } else {
+
+ phy_data |= IGP02E1000_PM_D0_LPLU;
+ ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
+ if (ret_val)
+ return ret_val;
+
/* When LPLU is enabled we should disable SmartSpeed */
ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
if(ret_val)
return E1000_SUCCESS;
}
-static int32_t
-e1000_polarity_reversal_workaround(struct e1000_hw *hw)
-{
- int32_t ret_val;
- uint16_t mii_status_reg;
- uint16_t i;
- /* Polarity reversal workaround for forced 10F/10H links. */
+/*****************************************************************************
+ * This function reads the cookie from ARC ram.
+ *
+ * returns: - E1000_SUCCESS .
+ ****************************************************************************/
+int32_t
+e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
+{
+ uint8_t i;
+ uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET;
+ uint8_t length = E1000_MNG_DHCP_COOKIE_LENGTH;
- /* Disable the transmitter on the PHY */
+ length = (length >> 2);
+ offset = (offset >> 2);
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+ for (i = 0; i < length; i++) {
+ *((uint32_t *) buffer + i) =
+ E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset + i);
+ }
+ return E1000_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * This function checks whether the HOST IF is enabled for command operaton
+ * and also checks whether the previous command is completed.
+ * It busy waits in case of previous command is not completed.
+ *
+ * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or
+ * timeout
+ * - E1000_SUCCESS for success.
+ ****************************************************************************/
+int32_t
+e1000_mng_enable_host_if(struct e1000_hw * hw)
+{
+ uint32_t hicr;
+ uint8_t i;
+
+ /* Check that the host interface is enabled. */
+ hicr = E1000_READ_REG(hw, HICR);
+ if ((hicr & E1000_HICR_EN) == 0) {
+ DEBUGOUT("E1000_HOST_EN bit disabled.\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+ /* check the previous command is completed */
+ for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
+ hicr = E1000_READ_REG(hw, HICR);
+ if (!(hicr & E1000_HICR_C))
+ break;
+ msec_delay_irq(1);
+ }
+
+ if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
+ DEBUGOUT("Previous command timeout failed .\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+ return E1000_SUCCESS;
+}
+
+/*****************************************************************************
+ * 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.
+ *
+ * returns - E1000_SUCCESS for success.
+ ****************************************************************************/
+int32_t
+e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+ uint16_t length, uint16_t offset, uint8_t *sum)
+{
+ uint8_t *tmp;
+ uint8_t *bufptr = buffer;
+ uint32_t data;
+ uint16_t remaining, i, j, prev_bytes;
+
+ /* sum = only sum of the data and it is not checksum */
+
+ if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
+ return -E1000_ERR_PARAM;
+ }
+
+ tmp = (uint8_t *)&data;
+ prev_bytes = offset & 0x3;
+ offset &= 0xFFFC;
+ offset >>= 2;
+
+ if (prev_bytes) {
+ data = E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset);
+ for (j = prev_bytes; j < sizeof(uint32_t); j++) {
+ *(tmp + j) = *bufptr++;
+ *sum += *(tmp + j);
+ }
+ E1000_WRITE_REG_ARRAY_DWORD(hw, 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(uint32_t); j++) {
+ *(tmp + j) = *bufptr++;
+ *sum += *(tmp + j);
+ }
+
+ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset + i, data);
+ }
+ if (remaining) {
+ for (j = 0; j < sizeof(uint32_t); j++) {
+ if (j < remaining)
+ *(tmp + j) = *bufptr++;
+ else
+ *(tmp + j) = 0;
+
+ *sum += *(tmp + j);
+ }
+ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset + i, data);
+ }
+
+ return E1000_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * This function writes the command header after does the checksum calculation.
+ *
+ * returns - E1000_SUCCESS for success.
+ ****************************************************************************/
+int32_t
+e1000_mng_write_cmd_header(struct e1000_hw * hw,
+ struct e1000_host_mng_command_header * hdr)
+{
+ uint16_t i;
+ uint8_t sum;
+ uint8_t *buffer;
+
+ /* Write the whole command header structure which includes sum of
+ * the buffer */
+
+ uint16_t length = sizeof(struct e1000_host_mng_command_header);
+
+ sum = hdr->checksum;
+ hdr->checksum = 0;
+
+ buffer = (uint8_t *) hdr;
+ i = length;
+ while(i--)
+ sum += buffer[i];
+
+ hdr->checksum = 0 - sum;
+
+ length >>= 2;
+ /* The device driver writes the relevant command block into the ram area. */
+ for (i = 0; i < length; i++)
+ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((uint32_t *) hdr + i));
+
+ return E1000_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * This function indicates to ARC that a new command is pending which completes
+ * one write operation by the driver.
+ *
+ * returns - E1000_SUCCESS for success.
+ ****************************************************************************/
+int32_t
+e1000_mng_write_commit(
+ struct e1000_hw * hw)
+{
+ uint32_t hicr;
+
+ hicr = E1000_READ_REG(hw, HICR);
+ /* Setting this bit tells the ARC that a new command is pending. */
+ E1000_WRITE_REG(hw, HICR, hicr | E1000_HICR_C);
+
+ return E1000_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * This function checks the mode of the firmware.
+ *
+ * returns - TRUE when the mode is IAMT or FALSE.
+ ****************************************************************************/
+boolean_t
+e1000_check_mng_mode(
+ struct e1000_hw *hw)
+{
+ uint32_t fwsm;
+
+ fwsm = E1000_READ_REG(hw, FWSM);
+
+ if((fwsm & E1000_FWSM_MODE_MASK) ==
+ (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/*****************************************************************************
+ * This function writes the dhcp info .
+ ****************************************************************************/
+int32_t
+e1000_mng_write_dhcp_info(struct e1000_hw * hw, uint8_t *buffer,
+ uint16_t length)
+{
+ int32_t ret_val;
+ struct e1000_host_mng_command_header hdr;
+
+ hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
+ hdr.command_length = length;
+ hdr.reserved1 = 0;
+ hdr.reserved2 = 0;
+ hdr.checksum = 0;
+
+ ret_val = e1000_mng_enable_host_if(hw);
+ if (ret_val == E1000_SUCCESS) {
+ ret_val = e1000_mng_host_if_write(hw, buffer, length, sizeof(hdr),
+ &(hdr.checksum));
+ if (ret_val == E1000_SUCCESS) {
+ ret_val = e1000_mng_write_cmd_header(hw, &hdr);
+ if (ret_val == E1000_SUCCESS)
+ ret_val = e1000_mng_write_commit(hw);
+ }
+ }
+ return ret_val;
+}
+
+
+/*****************************************************************************
+ * This function calculates the checksum.
+ *
+ * returns - checksum of buffer contents.
+ ****************************************************************************/
+uint8_t
+e1000_calculate_mng_checksum(char *buffer, uint32_t length)
+{
+ uint8_t sum = 0;
+ uint32_t i;
+
+ if (!buffer)
+ return 0;
+
+ for (i=0; i < length; i++)
+ sum += buffer[i];
+
+ return (uint8_t) (0 - sum);
+}
+
+/*****************************************************************************
+ * This function checks whether tx pkt filtering needs to be enabled or not.
+ *
+ * returns - TRUE for packet filtering or FALSE.
+ ****************************************************************************/
+boolean_t
+e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+{
+ /* called in init as well as watchdog timer functions */
+
+ int32_t ret_val, checksum;
+ boolean_t tx_filter = FALSE;
+ struct e1000_host_mng_dhcp_cookie *hdr = &(hw->mng_cookie);
+ uint8_t *buffer = (uint8_t *) &(hw->mng_cookie);
+
+ if (e1000_check_mng_mode(hw)) {
+ ret_val = e1000_mng_enable_host_if(hw);
+ if (ret_val == E1000_SUCCESS) {
+ ret_val = e1000_host_if_read_cookie(hw, buffer);
+ if (ret_val == E1000_SUCCESS) {
+ checksum = hdr->checksum;
+ hdr->checksum = 0;
+ if ((hdr->signature == E1000_IAMT_SIGNATURE) &&
+ checksum == e1000_calculate_mng_checksum((char *)buffer,
+ E1000_MNG_DHCP_COOKIE_LENGTH)) {
+ if (hdr->status &
+ E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT)
+ tx_filter = TRUE;
+ } else
+ tx_filter = TRUE;
+ } else
+ tx_filter = TRUE;
+ }
+ }
+
+ hw->tx_pkt_filtering = tx_filter;
+ return tx_filter;
+}
+
+/******************************************************************************
+ * Verifies the hardware needs to allow ARPs to be processed by the host
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * returns: - TRUE/FALSE
+ *
+ *****************************************************************************/
+uint32_t
+e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+{
+ uint32_t manc;
+ uint32_t fwsm, factps;
+
+ if (hw->asf_firmware_present) {
+ manc = E1000_READ_REG(hw, MANC);
+
+ if (!(manc & E1000_MANC_RCV_TCO_EN) ||
+ !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
+ return FALSE;
+ if (e1000_arc_subsystem_valid(hw) == TRUE) {
+ fwsm = E1000_READ_REG(hw, FWSM);
+ factps = E1000_READ_REG(hw, FACTPS);
+
+ if (((fwsm & E1000_FWSM_MODE_MASK) ==
+ (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)) &&
+ (factps & E1000_FACTPS_MNGCG))
+ return TRUE;
+ } else
+ if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int32_t
+e1000_polarity_reversal_workaround(struct e1000_hw *hw)
+{
+ int32_t ret_val;
+ uint16_t mii_status_reg;
+ uint16_t i;
+
+ /* Polarity reversal workaround for forced 10F/10H links. */
+
+ /* Disable the transmitter on the PHY */
+
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
if(ret_val)
return ret_val;
ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
return E1000_SUCCESS;
}
+/***************************************************************************
+ *
+ * Disables PCI-Express master access.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - none.
+ *
+ ***************************************************************************/
+void
+e1000_set_pci_express_master_disable(struct e1000_hw *hw)
+{
+ uint32_t ctrl;
+
+ DEBUGFUNC("e1000_set_pci_express_master_disable");
+
+ if (hw->bus_type != e1000_bus_type_pci_express)
+ return;
+
+ ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl |= E1000_CTRL_GIO_MASTER_DISABLE;
+ E1000_WRITE_REG(hw, CTRL, ctrl);
+}
+
+/***************************************************************************
+ *
+ * Enables PCI-Express master access.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - none.
+ *
+ ***************************************************************************/
+void
+e1000_enable_pciex_master(struct e1000_hw *hw)
+{
+ uint32_t ctrl;
+
+ DEBUGFUNC("e1000_enable_pciex_master");
+
+ if (hw->bus_type != e1000_bus_type_pci_express)
+ return;
+
+ ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl &= ~E1000_CTRL_GIO_MASTER_DISABLE;
+ E1000_WRITE_REG(hw, CTRL, ctrl);
+}
+
+/*******************************************************************************
+ *
+ * Disables PCI-Express master access and verifies there are no pending requests
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_ERR_MASTER_REQUESTS_PENDING if master disable bit hasn't
+ * caused the master requests to be disabled.
+ * E1000_SUCCESS master requests disabled.
+ *
+ ******************************************************************************/
+int32_t
+e1000_disable_pciex_master(struct e1000_hw *hw)
+{
+ int32_t timeout = MASTER_DISABLE_TIMEOUT; /* 80ms */
+
+ DEBUGFUNC("e1000_disable_pciex_master");
+
+ if (hw->bus_type != e1000_bus_type_pci_express)
+ return E1000_SUCCESS;
+
+ e1000_set_pci_express_master_disable(hw);
+
+ while(timeout) {
+ if(!(E1000_READ_REG(hw, STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
+ break;
+ else
+ udelay(100);
+ timeout--;
+ }
+
+ if(!timeout) {
+ DEBUGOUT("Master requests are pending.\n");
+ return -E1000_ERR_MASTER_REQUESTS_PENDING;
+ }
+
+ return E1000_SUCCESS;
+}
+
+/*******************************************************************************
+ *
+ * Check for EEPROM Auto Read bit done.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_ERR_RESET if fail to reset MAC
+ * E1000_SUCCESS at any other case.
+ *
+ ******************************************************************************/
+int32_t
+e1000_get_auto_rd_done(struct e1000_hw *hw)
+{
+ int32_t timeout = AUTO_READ_DONE_TIMEOUT;
+
+ DEBUGFUNC("e1000_get_auto_rd_done");
+
+ switch (hw->mac_type) {
+ default:
+ msec_delay(5);
+ break;
+ case e1000_82573:
+ while(timeout) {
+ if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break;
+ else msec_delay(1);
+ timeout--;
+ }
+
+ if(!timeout) {
+ DEBUGOUT("Auto read by HW from EEPROM has not completed.\n");
+ return -E1000_ERR_RESET;
+ }
+ break;
+ }
+
+ return E1000_SUCCESS;
+}
+
+/***************************************************************************
+ * Checks if the PHY configuration is done
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_ERR_RESET if fail to reset MAC
+ * E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+int32_t
+e1000_get_phy_cfg_done(struct e1000_hw *hw)
+{
+ DEBUGFUNC("e1000_get_phy_cfg_done");
+
+ /* Simply wait for 10ms */
+ msec_delay(10);
+
+ return E1000_SUCCESS;
+}
+
+/***************************************************************************
+ *
+ * Using the combination of SMBI and SWESMBI semaphore bits when resetting
+ * adapter or Eeprom access.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_ERR_EEPROM if fail to access EEPROM.
+ * E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+int32_t
+e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
+{
+ int32_t timeout;
+ uint32_t swsm;
+
+ DEBUGFUNC("e1000_get_hw_eeprom_semaphore");
+
+ if(!hw->eeprom_semaphore_present)
+ return E1000_SUCCESS;
+
+
+ /* Get the FW semaphore. */
+ timeout = hw->eeprom.word_size + 1;
+ while(timeout) {
+ swsm = E1000_READ_REG(hw, SWSM);
+ swsm |= E1000_SWSM_SWESMBI;
+ E1000_WRITE_REG(hw, SWSM, swsm);
+ /* if we managed to set the bit we got the semaphore. */
+ swsm = E1000_READ_REG(hw, SWSM);
+ if(swsm & E1000_SWSM_SWESMBI)
+ break;
+
+ udelay(50);
+ timeout--;
+ }
+
+ if(!timeout) {
+ /* Release semaphores */
+ e1000_put_hw_eeprom_semaphore(hw);
+ DEBUGOUT("Driver can't access the Eeprom - SWESMBI bit is set.\n");
+ return -E1000_ERR_EEPROM;
+ }
+
+ return E1000_SUCCESS;
+}
+
+/***************************************************************************
+ * This function clears HW semaphore bits.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - None.
+ *
+ ***************************************************************************/
+void
+e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
+{
+ uint32_t swsm;
+
+ DEBUGFUNC("e1000_put_hw_eeprom_semaphore");
+
+ if(!hw->eeprom_semaphore_present)
+ return;
+
+ swsm = E1000_READ_REG(hw, SWSM);
+ /* Release both semaphores. */
+ swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
+ E1000_WRITE_REG(hw, SWSM, swsm);
+}
+
+/******************************************************************************
+ * Checks if PHY reset is blocked due to SOL/IDER session, for example.
+ * Returning E1000_BLK_PHY_RESET isn't necessarily an error. But it's up to
+ * the caller to figure out how to deal with it.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_BLK_PHY_RESET
+ * E1000_SUCCESS
+ *
+ *****************************************************************************/
+int32_t
+e1000_check_phy_reset_block(struct e1000_hw *hw)
+{
+ uint32_t manc = 0;
+ if(hw->mac_type > e1000_82547_rev_2)
+ manc = E1000_READ_REG(hw, MANC);
+ return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
+ E1000_BLK_PHY_RESET : E1000_SUCCESS;
+}
+
+uint8_t
+e1000_arc_subsystem_valid(struct e1000_hw *hw)
+{
+ uint32_t fwsm;
+
+ /* On 8257x silicon, registers in the range of 0x8800 - 0x8FFC
+ * may not be provided a DMA clock when no manageability features are
+ * enabled. We do not want to perform any reads/writes to these registers
+ * if this is the case. We read FWSM to determine the manageability mode.
+ */
+ switch (hw->mac_type) {
+ case e1000_82573:
+ fwsm = E1000_READ_REG(hw, FWSM);
+ if((fwsm & E1000_FWSM_MODE_MASK) != 0)
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+
+
e1000_82541_rev_2,
e1000_82547,
e1000_82547_rev_2,
+ e1000_82573,
e1000_num_macs
} e1000_mac_type;
e1000_eeprom_uninitialized = 0,
e1000_eeprom_spi,
e1000_eeprom_microwire,
+ e1000_eeprom_flash,
e1000_num_eeprom_types
} e1000_eeprom_type;
e1000_bus_type_unknown = 0,
e1000_bus_type_pci,
e1000_bus_type_pcix,
+ e1000_bus_type_pci_express,
e1000_bus_type_reserved
} e1000_bus_type;
e1000_bus_speed_100,
e1000_bus_speed_120,
e1000_bus_speed_133,
+ e1000_bus_speed_2500,
e1000_bus_speed_reserved
} e1000_bus_speed;
e1000_bus_width_unknown = 0,
e1000_bus_width_32,
e1000_bus_width_64,
+ e1000_bus_width_pciex_1,
+ e1000_bus_width_pciex_4,
e1000_bus_width_reserved
} e1000_bus_width;
typedef enum {
e1000_phy_m88 = 0,
e1000_phy_igp,
+ e1000_phy_igp_2,
e1000_phy_undefined = 0xFF
} e1000_phy_type;
uint16_t address_bits;
uint16_t delay_usec;
uint16_t page_size;
+ boolean_t use_eerd;
+ boolean_t use_eewr;
};
+/* Flex ASF Information */
+#define E1000_HOST_IF_MAX_SIZE 2048
+
+typedef enum {
+ e1000_byte_align = 0,
+ e1000_word_align = 1,
+ e1000_dword_align = 2
+} e1000_align_type;
+
/* Error Codes */
#define E1000_ERR_PARAM 4
#define E1000_ERR_MAC_TYPE 5
#define E1000_ERR_PHY_TYPE 6
+#define E1000_ERR_RESET 9
+#define E1000_ERR_MASTER_REQUESTS_PENDING 10
+#define E1000_ERR_HOST_INTERFACE_COMMAND 11
+#define E1000_BLK_PHY_RESET 12
/* Function prototypes */
/* Initialization */
int32_t e1000_reset_hw(struct e1000_hw *hw);
int32_t e1000_init_hw(struct e1000_hw *hw);
+int32_t e1000_id_led_init(struct e1000_hw * hw);
int32_t e1000_set_mac_type(struct e1000_hw *hw);
void e1000_set_media_type(struct e1000_hw *hw);
/* PHY */
int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data);
int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
-void e1000_phy_hw_reset(struct e1000_hw *hw);
+int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
int32_t e1000_phy_reset(struct e1000_hw *hw);
int32_t e1000_detect_gig_phy(struct e1000_hw *hw);
int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
/* EEPROM Functions */
-void e1000_init_eeprom_params(struct e1000_hw *hw);
+int32_t e1000_init_eeprom_params(struct e1000_hw *hw);
+boolean_t e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);
+int32_t e1000_read_eeprom_eerd(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+int32_t e1000_write_eeprom_eewr(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+int32_t e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);
+
+/* MNG HOST IF functions */
+uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
+
+#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64
+#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 /* Host Interface data length */
+
+#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 /* Time in ms to process MNG command */
+#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 /* Cookie offset */
+#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 /* Cookie length */
+#define E1000_MNG_IAMT_MODE 0x3
+#define E1000_IAMT_SIGNATURE 0x544D4149 /* Intel(R) Active Management Technology signature */
+
+#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT 0x1 /* DHCP parsing enabled */
+#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT 0x2 /* DHCP parsing enabled */
+#define E1000_VFTA_ENTRY_SHIFT 0x5
+#define E1000_VFTA_ENTRY_MASK 0x7F
+#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F
+
+struct e1000_host_mng_command_header {
+ uint8_t command_id;
+ uint8_t checksum;
+ uint16_t reserved1;
+ uint16_t reserved2;
+ uint16_t command_length;
+};
+
+struct e1000_host_mng_command_info {
+ struct e1000_host_mng_command_header command_header; /* Command Head/Command Result Head has 4 bytes */
+ uint8_t command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; /* Command data can length 0..0x658*/
+};
+#ifdef __BIG_ENDIAN
+struct e1000_host_mng_dhcp_cookie{
+ uint32_t signature;
+ uint16_t vlan_id;
+ uint8_t reserved0;
+ uint8_t status;
+ uint32_t reserved1;
+ uint8_t checksum;
+ uint8_t reserved3;
+ uint16_t reserved2;
+};
+#else
+struct e1000_host_mng_dhcp_cookie{
+ uint32_t signature;
+ uint8_t status;
+ uint8_t reserved0;
+ uint16_t vlan_id;
+ uint32_t reserved1;
+ uint16_t reserved2;
+ uint8_t reserved3;
+ uint8_t checksum;
+};
+#endif
+
+int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer,
+ uint16_t length);
+boolean_t e1000_check_mng_mode(struct e1000_hw *hw);
+boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
+int32_t e1000_mng_enable_host_if(struct e1000_hw *hw);
+int32_t e1000_mng_host_if_write(struct e1000_hw *hw, uint8_t *buffer,
+ uint16_t length, uint16_t offset, uint8_t *sum);
+int32_t e1000_mng_write_cmd_header(struct e1000_hw* hw,
+ struct e1000_host_mng_command_header* hdr);
+
+int32_t e1000_mng_write_commit(struct e1000_hw *hw);
+
int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw);
int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw);
int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num);
int32_t e1000_read_mac_addr(struct e1000_hw * hw);
+int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
+void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
/* Filters (multicast, vlan, receive) */
void e1000_init_rx_addrs(struct e1000_hw *hw);
/* Adaptive IFS Functions */
/* Everything else */
-uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
void e1000_clear_hw_cntrs(struct e1000_hw *hw);
void e1000_reset_adaptive(struct e1000_hw *hw);
void e1000_update_adaptive(struct e1000_hw *hw);
void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value);
int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, boolean_t link_up);
int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
+int32_t e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active);
+void e1000_set_pci_express_master_disable(struct e1000_hw *hw);
+void e1000_enable_pciex_master(struct e1000_hw *hw);
+int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
+int32_t e1000_get_auto_rd_done(struct e1000_hw *hw);
+int32_t e1000_get_phy_cfg_done(struct e1000_hw *hw);
+int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
+void e1000_release_software_semaphore(struct e1000_hw *hw);
+int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
+int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
+void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
+int32_t e1000_commit_shadow_ram(struct e1000_hw *hw);
+uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw);
#define E1000_READ_REG_IO(a, reg) \
e1000_read_reg_io((a), E1000_##reg)
#define E1000_DEV_ID_82546GB_SERDES 0x107B
#define E1000_DEV_ID_82546GB_PCIE 0x108A
#define E1000_DEV_ID_82547EI 0x1019
+#define E1000_DEV_ID_82573E 0x108B
+#define E1000_DEV_ID_82573E_IAMT 0x108C
+
+#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
#define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6
#define E1000_REVISION_0 0
#define E1000_REVISION_1 1
#define E1000_REVISION_2 2
+#define E1000_REVISION_3 3
#define SPEED_10 10
#define SPEED_100 100
E1000_IMS_RXSEQ | \
E1000_IMS_LSC)
+
/* Number of high/low register pairs in the RAR. The RAR (Receive Address
* Registers) holds the directed and multicast addresses that we monitor. We
* reserve one of these spots for our directed address, allowing us room for
uint16_t special;
};
+/* Receive Descriptor - Extended */
+union e1000_rx_desc_extended {
+ struct {
+ uint64_t buffer_addr;
+ uint64_t reserved;
+ } read;
+ struct {
+ struct {
+ uint32_t mrq; /* Multiple Rx Queues */
+ union {
+ uint32_t rss; /* RSS Hash */
+ struct {
+ uint16_t ip_id; /* IP id */
+ uint16_t csum; /* Packet Checksum */
+ } csum_ip;
+ } hi_dword;
+ } lower;
+ struct {
+ uint32_t status_error; /* ext status/error */
+ uint16_t length;
+ uint16_t vlan; /* VLAN tag */
+ } upper;
+ } wb; /* writeback */
+};
+
+#define MAX_PS_BUFFERS 4
+/* Receive Descriptor - Packet Split */
+union e1000_rx_desc_packet_split {
+ struct {
+ /* one buffer for protocol header(s), three data buffers */
+ uint64_t buffer_addr[MAX_PS_BUFFERS];
+ } read;
+ struct {
+ struct {
+ uint32_t mrq; /* Multiple Rx Queues */
+ union {
+ uint32_t rss; /* RSS Hash */
+ struct {
+ uint16_t ip_id; /* IP id */
+ uint16_t csum; /* Packet Checksum */
+ } csum_ip;
+ } hi_dword;
+ } lower;
+ struct {
+ uint32_t status_error; /* ext status/error */
+ uint16_t length0; /* length of buffer 0 */
+ uint16_t vlan; /* VLAN tag */
+ } middle;
+ struct {
+ uint16_t header_status;
+ uint16_t length[3]; /* length of buffers 1-3 */
+ } upper;
+ uint64_t reserved;
+ } wb; /* writeback */
+};
+
/* Receive Decriptor bit definitions */
#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */
#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
+#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum caculated */
#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */
+#define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */
+#define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */
+#define E1000_RXD_STAT_ACK 0x8000 /* ACK Packet indication */
#define E1000_RXD_ERR_CE 0x01 /* CRC Error */
#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */
#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */
#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */
-#define E1000_RXD_SPC_PRI_SHIFT 0x000D /* Priority is in upper 3 of 16 */
+#define E1000_RXD_SPC_PRI_SHIFT 13
#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */
-#define E1000_RXD_SPC_CFI_SHIFT 0x000C /* CFI is bit 12 */
+#define E1000_RXD_SPC_CFI_SHIFT 12
+
+#define E1000_RXDEXT_STATERR_CE 0x01000000
+#define E1000_RXDEXT_STATERR_SE 0x02000000
+#define E1000_RXDEXT_STATERR_SEQ 0x04000000
+#define E1000_RXDEXT_STATERR_CXE 0x10000000
+#define E1000_RXDEXT_STATERR_TCPE 0x20000000
+#define E1000_RXDEXT_STATERR_IPE 0x40000000
+#define E1000_RXDEXT_STATERR_RXE 0x80000000
+
+#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000
+#define E1000_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF
/* mask to determine if packets should be dropped due to frame errors */
#define E1000_RXD_ERR_FRAME_ERR_MASK ( \
E1000_RXD_ERR_CXE | \
E1000_RXD_ERR_RXE)
+
+/* Same mask, but for extended and packet split descriptors */
+#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \
+ E1000_RXDEXT_STATERR_CE | \
+ E1000_RXDEXT_STATERR_SE | \
+ E1000_RXDEXT_STATERR_SEQ | \
+ E1000_RXDEXT_STATERR_CXE | \
+ E1000_RXDEXT_STATERR_RXE)
+
/* Transmit Descriptor */
struct e1000_tx_desc {
uint64_t buffer_addr; /* Address of the descriptor's data buffer */
#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_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_PBA 0x01000 /* Packet Buffer Allocation - RW */
+#define E1000_PBS 0x01008 /* Packet Buffer Size */
+#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
+#define E1000_FLASH_UPDATES 1000
+#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_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_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */
#define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */
#define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */
#define E1000_RXDCTL 0x02828 /* RX Descriptor Control - RW */
#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */
#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_TDFH 0x03410 /* TX Data FIFO Head - RW */
#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */
#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */
#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */
#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
+#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */
+#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */
+#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */
+#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */
+#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */
+#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */
+#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */
+#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */
#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_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 0x4100 /* Interrupt Assertion Count */
+#define E1000_ICRXPTC 0x4104 /* Interrupt Cause Rx Packet Timer Expire Count */
+#define E1000_ICRXATC 0x4108 /* Interrupt Cause Rx Absolute Timer Expire Count */
+#define E1000_ICTXPTC 0x410C /* Interrupt Cause Tx Packet Timer Expire Count */
+#define E1000_ICTXATC 0x4110 /* Interrupt Cause Tx Absolute Timer Expire Count */
+#define E1000_ICTXQEC 0x4118 /* Interrupt Cause Tx Queue Empty Count */
+#define E1000_ICTXQMTC 0x411C /* Interrupt Cause Tx Queue Minimum Threshold Count */
+#define E1000_ICRXDMTC 0x4120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
+#define E1000_ICRXOC 0x4124 /* Interrupt Cause Receiver Overrun Count */
#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */
+#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_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
+#define E1000_GCR 0x05B00 /* PCI-Ex Control */
+#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_FFLT_DBG 0x05F04 /* Debug Register */
+#define E1000_HICR 0x08F00 /* Host Inteface Control */
/* Register Set (82542)
*
* Some of the 82542 registers are located at different offsets than they are
#define E1000_82542_VFTA 0x00600
#define E1000_82542_LEDCTL E1000_LEDCTL
#define E1000_82542_PBA E1000_PBA
+#define E1000_82542_PBS E1000_PBS
+#define E1000_82542_EEMNGCTL E1000_EEMNGCTL
+#define E1000_82542_EEARBC E1000_EEARBC
+#define E1000_82542_FLASHT E1000_FLASHT
+#define E1000_82542_EEWR E1000_EEWR
+#define E1000_82542_FLSWCTL E1000_FLSWCTL
+#define E1000_82542_FLSWDATA E1000_FLSWDATA
+#define E1000_82542_FLSWCNT E1000_FLSWCNT
+#define E1000_82542_FLOP E1000_FLOP
+#define E1000_82542_EXTCNF_CTRL E1000_EXTCNF_CTRL
+#define E1000_82542_EXTCNF_SIZE E1000_EXTCNF_SIZE
+#define E1000_82542_ERT E1000_ERT
#define E1000_82542_RXDCTL E1000_RXDCTL
#define E1000_82542_RADV E1000_RADV
#define E1000_82542_RSRPD E1000_RSRPD
#define E1000_82542_FFMT E1000_FFMT
#define E1000_82542_FFVT E1000_FFVT
#define E1000_82542_HOST_IF E1000_HOST_IF
+#define E1000_82542_IAM E1000_IAM
+#define E1000_82542_EEMNGCTL E1000_EEMNGCTL
+#define E1000_82542_PSRCTL E1000_PSRCTL
+#define E1000_82542_RAID E1000_RAID
+#define E1000_82542_TARC0 E1000_TARC0
+#define E1000_82542_TDBAL1 E1000_TDBAL1
+#define E1000_82542_TDBAH1 E1000_TDBAH1
+#define E1000_82542_TDLEN1 E1000_TDLEN1
+#define E1000_82542_TDH1 E1000_TDH1
+#define E1000_82542_TDT1 E1000_TDT1
+#define E1000_82542_TXDCTL1 E1000_TXDCTL1
+#define E1000_82542_TARC1 E1000_TARC1
+#define E1000_82542_RFCTL E1000_RFCTL
+#define E1000_82542_GCR E1000_GCR
+#define E1000_82542_GSCL_1 E1000_GSCL_1
+#define E1000_82542_GSCL_2 E1000_GSCL_2
+#define E1000_82542_GSCL_3 E1000_GSCL_3
+#define E1000_82542_GSCL_4 E1000_GSCL_4
+#define E1000_82542_FACTPS E1000_FACTPS
+#define E1000_82542_SWSM E1000_SWSM
+#define E1000_82542_FWSM E1000_FWSM
+#define E1000_82542_FFLT_DBG E1000_FFLT_DBG
+#define E1000_82542_IAC E1000_IAC
+#define E1000_82542_ICRXPTC E1000_ICRXPTC
+#define E1000_82542_ICRXATC E1000_ICRXATC
+#define E1000_82542_ICTXPTC E1000_ICTXPTC
+#define E1000_82542_ICTXATC E1000_ICTXATC
+#define E1000_82542_ICTXQEC E1000_ICTXQEC
+#define E1000_82542_ICTXQMTC E1000_ICTXQMTC
+#define E1000_82542_ICRXDMTC E1000_ICRXDMTC
+#define E1000_82542_ICRXOC E1000_ICRXOC
+#define E1000_82542_HICR E1000_HICR
/* Statistics counters collected by the MAC */
struct e1000_hw_stats {
uint64_t bptc;
uint64_t tsctc;
uint64_t tsctfc;
+ uint64_t iac;
+ uint64_t icrxptc;
+ uint64_t icrxatc;
+ uint64_t ictxptc;
+ uint64_t ictxatc;
+ uint64_t ictxqec;
+ uint64_t ictxqmtc;
+ uint64_t icrxdmtc;
+ uint64_t icrxoc;
};
/* Structure containing variables used by the shared code (e1000_hw.c) */
struct e1000_hw {
- uint8_t __iomem *hw_addr;
+ uint8_t *hw_addr;
+ uint8_t *flash_address;
e1000_mac_type mac_type;
e1000_phy_type phy_type;
uint32_t phy_init_script;
e1000_ms_type original_master_slave;
e1000_ffe_config ffe_config_state;
uint32_t asf_firmware_present;
+ uint32_t eeprom_semaphore_present;
unsigned long io_base;
uint32_t phy_id;
uint32_t phy_revision;
uint32_t ledctl_default;
uint32_t ledctl_mode1;
uint32_t ledctl_mode2;
+ boolean_t tx_pkt_filtering;
+ struct e1000_host_mng_dhcp_cookie mng_cookie;
uint16_t phy_spd_default;
uint16_t autoneg_advertised;
uint16_t pci_cmd_word;
boolean_t adaptive_ifs;
boolean_t ifs_params_forced;
boolean_t in_ifs_mode;
+ boolean_t mng_reg_access_disabled;
};
#define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */
#define E1000_EEPROM_LED_LOGIC 0x0020 /* Led Logic Word */
+#define E1000_EEPROM_RW_REG_DATA 16 /* Offset to data in EEPROM read/write registers */
+#define E1000_EEPROM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
+#define E1000_EEPROM_RW_REG_START 1 /* First bit for telling part to start operation */
+#define E1000_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
+#define E1000_EEPROM_POLL_WRITE 1 /* Flag for polling for write complete */
+#define E1000_EEPROM_POLL_READ 0 /* Flag for polling for read complete */
/* Register Bit Masks */
/* Device Control */
#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */
#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */
#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */
+#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */
#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */
#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */
#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */
#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */
#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
+#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */
#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */
+#define E1000_STATUS_FUNC_SHIFT 2
#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */
#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */
#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */
#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */
+#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */
+#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */
#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */
#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */
#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */
#ifndef E1000_EEPROM_GRANT_ATTEMPTS
#define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */
#endif
+#define E1000_EECD_AUTO_RD 0x00000200 /* EEPROM Auto Read done */
+#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* EEprom Size */
+#define E1000_EECD_SIZE_EX_SHIFT 11
+#define E1000_EECD_NVADDS 0x00018000 /* NVM Address Size */
+#define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */
+#define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */
+#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */
+#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */
+#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */
+#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
+#define E1000_STM_OPCODE 0xDB00
+#define E1000_HICR_FW_RESET 0xC0
/* EEPROM Read */
#define E1000_EERD_START 0x00000001 /* Start Read */
#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000
#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000
#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000
+#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */
+#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */
/* MDI Control */
#define E1000_MDIC_DATA_MASK 0x0000FFFF
/* LED Control */
#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F
#define E1000_LEDCTL_LED0_MODE_SHIFT 0
+#define E1000_LEDCTL_LED0_BLINK_RATE 0x0000020
#define E1000_LEDCTL_LED0_IVRT 0x00000040
#define E1000_LEDCTL_LED0_BLINK 0x00000080
#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00
#define E1000_LEDCTL_LED1_MODE_SHIFT 8
+#define E1000_LEDCTL_LED1_BLINK_RATE 0x0002000
#define E1000_LEDCTL_LED1_IVRT 0x00004000
#define E1000_LEDCTL_LED1_BLINK 0x00008000
#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000
#define E1000_LEDCTL_LED2_MODE_SHIFT 16
+#define E1000_LEDCTL_LED2_BLINK_RATE 0x00200000
#define E1000_LEDCTL_LED2_IVRT 0x00400000
#define E1000_LEDCTL_LED2_BLINK 0x00800000
#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000
#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */
#define E1000_ICR_TXD_LOW 0x00008000
#define E1000_ICR_SRPD 0x00010000
+#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */
+#define E1000_ICR_MNG 0x00040000 /* Manageability event */
+#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */
+#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */
/* Interrupt Cause Set */
#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW
#define E1000_ICS_SRPD E1000_ICR_SRPD
+#define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */
+#define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */
+#define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */
/* Interrupt Mask Set */
#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW
#define E1000_IMS_SRPD E1000_ICR_SRPD
+#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */
+#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */
+#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */
/* Interrupt Mask Clear */
#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */
#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW
#define E1000_IMC_SRPD E1000_ICR_SRPD
+#define E1000_IMC_ACK E1000_ICR_ACK /* Receive Ack frame */
+#define E1000_IMC_MNG E1000_ICR_MNG /* Manageability event */
+#define E1000_IMC_DOCK E1000_ICR_DOCK /* Dock/Undock */
/* Receive Control */
#define E1000_RCTL_RST 0x00000001 /* Software reset */
#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */
#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
+#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */
+#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */
#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */
#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */
#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */
#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */
#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
+#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */
+#define E1000_RCTL_FLXBUF_SHIFT 27 /* Flexible buffer shift */
+
+/* Use byte values for the following shift parameters
+ * Usage:
+ * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
+ * E1000_PSRCTL_BSIZE0_MASK) |
+ * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) &
+ * E1000_PSRCTL_BSIZE1_MASK) |
+ * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) &
+ * E1000_PSRCTL_BSIZE2_MASK) |
+ * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |;
+ * E1000_PSRCTL_BSIZE3_MASK))
+ * where value0 = [128..16256], default=256
+ * value1 = [1024..64512], default=4096
+ * value2 = [0..64512], default=4096
+ * value3 = [0..64512], default=0
+ */
+
+#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F
+#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00
+#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000
+#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000
+
+#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */
+#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */
+#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */
+#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */
/* Receive Descriptor */
#define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */
#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */
#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */
+/* Header split receive */
+#define E1000_RFCTL_ISCSI_DIS 0x00000001
+#define E1000_RFCTL_ISCSI_DWC_MASK 0x0000003E
+#define E1000_RFCTL_ISCSI_DWC_SHIFT 1
+#define E1000_RFCTL_NFSW_DIS 0x00000040
+#define E1000_RFCTL_NFSR_DIS 0x00000080
+#define E1000_RFCTL_NFS_VER_MASK 0x00000300
+#define E1000_RFCTL_NFS_VER_SHIFT 8
+#define E1000_RFCTL_IPV6_DIS 0x00000400
+#define E1000_RFCTL_IPV6_XSUM_DIS 0x00000800
+#define E1000_RFCTL_ACK_DIS 0x00001000
+#define E1000_RFCTL_ACKD_DIS 0x00002000
+#define E1000_RFCTL_IPFRSP_DIS 0x00004000
+#define E1000_RFCTL_EXTEN 0x00008000
+#define E1000_RFCTL_IPV6_EX_DIS 0x00010000
+#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000
+
/* Receive Descriptor Control */
#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */
#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */
#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */
#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
+#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.
+ still to be processed. */
/* Transmit Configuration Word */
#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */
#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */
#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */
+#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */
/* Receive Checksum Control */
#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */
#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */
#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */
#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */
+#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
+#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
+
/* Definitions for power management and wakeup registers */
/* Wake Up Control */
#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */
#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */
+#define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */
#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */
#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */
#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */
#define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery
* Filtering */
+#define E1000_MANC_ARP_RES_EN 0x00008000 /* Enable ARP response Filtering */
#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */
#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
+#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MAC address
* filtering */
#define E1000_MANC_EN_MNG2HOST 0x00200000 /* Enable MNG packets to host
* memory */
+#define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000 /* Enable IP address
+ * filtering */
+#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable checksum filtering */
+#define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */
#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */
#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */
#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */
#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */
#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */
+/* SW Semaphore Register */
+#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
+#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
+#define E1000_SWSM_WMNG 0x00000004 /* Wake MNG Clock */
+#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */
+
+/* FW Semaphore Register */
+#define E1000_FWSM_MODE_MASK 0x0000000E /* FW mode */
+#define E1000_FWSM_MODE_SHIFT 1
+#define E1000_FWSM_FW_VALID 0x00008000 /* FW established a valid mode */
+
+/* FFLT Debug Register */
+#define E1000_FFLT_DBG_INVC 0x00100000 /* Invalid /C/ code handling */
+
+typedef enum {
+ e1000_mng_mode_none = 0,
+ e1000_mng_mode_asf,
+ e1000_mng_mode_pt,
+ e1000_mng_mode_ipmi,
+ e1000_mng_mode_host_interface_only
+} e1000_mng_mode;
+
+/* Host Inteface Control Register */
+#define E1000_HICR_EN 0x00000001 /* Enable Bit - RO */
+#define E1000_HICR_C 0x00000002 /* Driver sets this bit when done
+ * to put command in RAM */
+#define E1000_HICR_SV 0x00000004 /* Status Validity */
+#define E1000_HICR_FWR 0x00000080 /* FW reset. Set by the Host */
+
+/* Host Interface Command Interface - Address range 0x8800-0x8EFF */
+#define E1000_HI_MAX_DATA_LENGTH 252 /* Host Interface data length */
+#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Number of bytes in range */
+#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Number of dwords in range */
+#define E1000_HI_COMMAND_TIMEOUT 500 /* Time in ms to process HI command */
+
+struct e1000_host_command_header {
+ uint8_t command_id;
+ uint8_t command_length;
+ uint8_t command_options; /* I/F bits for command, status for return */
+ uint8_t checksum;
+};
+struct e1000_host_command_info {
+ struct e1000_host_command_header command_header; /* Command Head/Command Result Head has 4 bytes */
+ uint8_t command_data[E1000_HI_MAX_DATA_LENGTH]; /* Command data can length 0..252 */
+};
+
+/* Host SMB register #0 */
+#define E1000_HSMC0R_CLKIN 0x00000001 /* SMB Clock in */
+#define E1000_HSMC0R_DATAIN 0x00000002 /* SMB Data in */
+#define E1000_HSMC0R_DATAOUT 0x00000004 /* SMB Data out */
+#define E1000_HSMC0R_CLKOUT 0x00000008 /* SMB Clock out */
+
+/* Host SMB register #1 */
+#define E1000_HSMC1R_CLKIN E1000_HSMC0R_CLKIN
+#define E1000_HSMC1R_DATAIN E1000_HSMC0R_DATAIN
+#define E1000_HSMC1R_DATAOUT E1000_HSMC0R_DATAOUT
+#define E1000_HSMC1R_CLKOUT E1000_HSMC0R_CLKOUT
+
+/* FW Status Register */
+#define E1000_FWSTS_FWS_MASK 0x000000FF /* FW Status */
+
/* Wake Up Packet Length */
#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */
#define E1000_MDALIGN 4096
+#define E1000_GCR_BEM32 0x00400000
+/* Function Active and Power State to MNG */
+#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003
+#define E1000_FACTPS_LAN0_VALID 0x00000004
+#define E1000_FACTPS_FUNC0_AUX_EN 0x00000008
+#define E1000_FACTPS_FUNC1_POWER_STATE_MASK 0x000000C0
+#define E1000_FACTPS_FUNC1_POWER_STATE_SHIFT 6
+#define E1000_FACTPS_LAN1_VALID 0x00000100
+#define E1000_FACTPS_FUNC1_AUX_EN 0x00000200
+#define E1000_FACTPS_FUNC2_POWER_STATE_MASK 0x00003000
+#define E1000_FACTPS_FUNC2_POWER_STATE_SHIFT 12
+#define E1000_FACTPS_IDE_ENABLE 0x00004000
+#define E1000_FACTPS_FUNC2_AUX_EN 0x00008000
+#define E1000_FACTPS_FUNC3_POWER_STATE_MASK 0x000C0000
+#define E1000_FACTPS_FUNC3_POWER_STATE_SHIFT 18
+#define E1000_FACTPS_SP_ENABLE 0x00100000
+#define E1000_FACTPS_FUNC3_AUX_EN 0x00200000
+#define E1000_FACTPS_FUNC4_POWER_STATE_MASK 0x03000000
+#define E1000_FACTPS_FUNC4_POWER_STATE_SHIFT 24
+#define E1000_FACTPS_IPMI_ENABLE 0x04000000
+#define E1000_FACTPS_FUNC4_AUX_EN 0x08000000
+#define E1000_FACTPS_MNGCG 0x20000000
+#define E1000_FACTPS_LAN_FUNC_SEL 0x40000000
+#define E1000_FACTPS_PM_STATE_CHANGED 0x80000000
+
/* EEPROM Commands - Microwire */
#define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */
#define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */
/* EEPROM Commands - SPI */
#define EEPROM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */
-#define EEPROM_READ_OPCODE_SPI 0x3 /* EEPROM read opcode */
-#define EEPROM_WRITE_OPCODE_SPI 0x2 /* EEPROM write opcode */
-#define EEPROM_A8_OPCODE_SPI 0x8 /* opcode bit-3 = address bit-8 */
-#define EEPROM_WREN_OPCODE_SPI 0x6 /* EEPROM set Write Enable latch */
-#define EEPROM_WRDI_OPCODE_SPI 0x4 /* EEPROM reset Write Enable latch */
-#define EEPROM_RDSR_OPCODE_SPI 0x5 /* EEPROM read Status register */
-#define EEPROM_WRSR_OPCODE_SPI 0x1 /* EEPROM write Status register */
+#define EEPROM_READ_OPCODE_SPI 0x03 /* EEPROM read opcode */
+#define EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */
+#define EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */
+#define EEPROM_WREN_OPCODE_SPI 0x06 /* EEPROM set Write Enable latch */
+#define EEPROM_WRDI_OPCODE_SPI 0x04 /* EEPROM reset Write Enable latch */
+#define EEPROM_RDSR_OPCODE_SPI 0x05 /* EEPROM read Status register */
+#define EEPROM_WRSR_OPCODE_SPI 0x01 /* EEPROM write Status register */
+#define EEPROM_ERASE4K_OPCODE_SPI 0x20 /* EEPROM ERASE 4KB */
+#define EEPROM_ERASE64K_OPCODE_SPI 0xD8 /* EEPROM ERASE 64KB */
+#define EEPROM_ERASE256_OPCODE_SPI 0xDB /* EEPROM ERASE 256B */
/* EEPROM Size definitions */
-#define EEPROM_SIZE_16KB 0x1800
-#define EEPROM_SIZE_8KB 0x1400
-#define EEPROM_SIZE_4KB 0x1000
-#define EEPROM_SIZE_2KB 0x0C00
-#define EEPROM_SIZE_1KB 0x0800
-#define EEPROM_SIZE_512B 0x0400
-#define EEPROM_SIZE_128B 0x0000
+#define EEPROM_WORD_SIZE_SHIFT 6
+#define EEPROM_SIZE_SHIFT 10
#define EEPROM_SIZE_MASK 0x1C00
/* EEPROM Word Offsets */
#define IFS_MIN 40
#define IFS_RATIO 4
+/* Extended Configuration Control and Size */
+#define E1000_EXTCNF_CTRL_PCIE_WRITE_ENABLE 0x00000001
+#define E1000_EXTCNF_CTRL_PHY_WRITE_ENABLE 0x00000002
+#define E1000_EXTCNF_CTRL_D_UD_ENABLE 0x00000004
+#define E1000_EXTCNF_CTRL_D_UD_LATENCY 0x00000008
+#define E1000_EXTCNF_CTRL_D_UD_OWNER 0x00000010
+#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020
+#define E1000_EXTCNF_CTRL_MDIO_HW_OWNERSHIP 0x00000040
+#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER 0x1FFF0000
+
+#define E1000_EXTCNF_SIZE_EXT_PHY_LENGTH 0x000000FF
+#define E1000_EXTCNF_SIZE_EXT_DOCK_LENGTH 0x0000FF00
+#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH 0x00FF0000
+
/* PBA constants */
+#define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */
#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */
#define E1000_PBA_22K 0x0016
#define E1000_PBA_24K 0x0018
/* Number of milliseconds we wait for auto-negotiation to complete */
#define LINK_UP_TIMEOUT 500
+/* Number of 100 microseconds we wait for PCI Express master disable */
+#define MASTER_DISABLE_TIMEOUT 800
+/* Number of milliseconds we wait for Eeprom auto read bit done after MAC reset */
+#define AUTO_READ_DONE_TIMEOUT 10
+/* Number of milliseconds we wait for PHY configuration done after MAC reset */
+#define PHY_CFG_TIMEOUT 40
+
#define E1000_TX_BUFFER_SIZE ((uint32_t)1514)
/* The carrier extension symbol, as received by the NIC. */
#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health Register */
#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO Register */
#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality Register */
+#define IGP02E1000_PHY_POWER_MGMT 0x19
#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* PHY Page Select Core Register */
/* IGP01E1000 AGC Registers - stores the cable length values*/
#define IGP01E1000_PHY_AGC_C 0x1472
#define IGP01E1000_PHY_AGC_D 0x1872
+/* IGP02E1000 AGC Registers for cable length values */
+#define IGP02E1000_PHY_AGC_A 0x11B1
+#define IGP02E1000_PHY_AGC_B 0x12B1
+#define IGP02E1000_PHY_AGC_C 0x14B1
+#define IGP02E1000_PHY_AGC_D 0x18B1
+
/* IGP01E1000 DSP Reset Register */
#define IGP01E1000_PHY_DSP_RESET 0x1F33
#define IGP01E1000_PHY_DSP_SET 0x1F71
#define IGP01E1000_PHY_DSP_FFE 0x1F35
#define IGP01E1000_PHY_CHANNEL_NUM 4
+#define IGP02E1000_PHY_CHANNEL_NUM 4
+
#define IGP01E1000_PHY_AGC_PARAM_A 0x1171
#define IGP01E1000_PHY_AGC_PARAM_B 0x1271
#define IGP01E1000_PHY_AGC_PARAM_C 0x1471
#define IGP01E1000_MSE_CHANNEL_B 0x0F00
#define IGP01E1000_MSE_CHANNEL_A 0xF000
+#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */
+#define IGP02E1000_PM_D3_LPLU 0x0004 /* Enable LPLU in non-D0a modes */
+#define IGP02E1000_PM_D0_LPLU 0x0002 /* Enable LPLU in D0a mode */
+
/* IGP01E1000 DSP reset macros */
#define DSP_RESET_ENABLE 0x0
#define DSP_RESET_DISABLE 0x2
#define E1000_MAX_DSP_RESETS 10
-/* IGP01E1000 AGC Registers */
+/* IGP01E1000 & IGP02E1000 AGC Registers */
#define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */
+#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Coarse - 15:13, Fine - 12:9 */
+
+/* IGP02E1000 AGC Register Length 9-bit mask */
+#define IGP02E1000_AGC_LENGTH_MASK 0x7F
/* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */
#define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128
+#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 128
-/* The precision of the length is +/- 10 meters */
+/* The precision error of the cable length is +/- 10 meters */
#define IGP01E1000_AGC_RANGE 10
+#define IGP02E1000_AGC_RANGE 10
/* IGP01E1000 PCS Initialization register */
/* bits 3:6 in the PCS registers stores the channels polarity */
#define M88E1000_12_PHY_ID M88E1000_E_PHY_ID
#define M88E1000_14_PHY_ID M88E1000_E_PHY_ID
#define M88E1011_I_REV_4 0x04
+#define M88E1111_I_PHY_ID 0x01410CC0
+#define L1LXT971A_PHY_ID 0x001378E0
/* Miscellaneous PHY bit definitions. */
#define PHY_PREAMBLE 0xFFFFFFFF
static int e1000_clean(struct net_device *netdev, int *budget);
static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
int *work_done, int work_to_do);
+static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ int *work_done, int work_to_do);
#else
static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter);
+static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter);
#endif
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
+static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter);
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
E1000_WRITE_FLUSH(&adapter->hw);
}
}
-
+void
+e1000_update_mng_vlan(struct e1000_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ uint16_t vid = adapter->hw.mng_cookie.vlan_id;
+ uint16_t old_vid = adapter->mng_vlan_id;
+ if(adapter->vlgrp) {
+ if(!adapter->vlgrp->vlan_devices[vid]) {
+ if(adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
+ e1000_vlan_rx_add_vid(netdev, vid);
+ adapter->mng_vlan_id = vid;
+ } else
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+
+ if((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
+ (vid != old_vid) &&
+ !adapter->vlgrp->vlan_devices[old_vid])
+ e1000_vlan_rx_kill_vid(netdev, old_vid);
+ }
+ }
+}
+
int
e1000_up(struct e1000_adapter *adapter)
{
e1000_configure_tx(adapter);
e1000_setup_rctl(adapter);
e1000_configure_rx(adapter);
- e1000_alloc_rx_buffers(adapter);
+ adapter->alloc_rx_buf(adapter);
#ifdef CONFIG_PCI_MSI
if(adapter->hw.mac_type > e1000_82547_rev_2) {
e1000_clean_rx_ring(adapter);
/* If WoL is not enabled
+ * and management mode is not IAMT
* Power down the PHY so no link is implied when interface is down */
- if(!adapter->wol && adapter->hw.media_type == e1000_media_type_copper) {
+ if(!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
+ adapter->hw.media_type == e1000_media_type_copper &&
+ !e1000_check_mng_mode(&adapter->hw) &&
+ !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN)) {
uint16_t mii_reg;
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
void
e1000_reset(struct e1000_adapter *adapter)
{
- uint32_t pba;
+ uint32_t pba, manc;
/* Repartition Pba for greater than 9k mtu
* To take effect CTRL.RST is required.
*/
- if(adapter->hw.mac_type < e1000_82547) {
- if(adapter->rx_buffer_len > E1000_RXBUFFER_8192)
- pba = E1000_PBA_40K;
- else
- pba = E1000_PBA_48K;
- } else {
- if(adapter->rx_buffer_len > E1000_RXBUFFER_8192)
- pba = E1000_PBA_22K;
- else
- pba = E1000_PBA_30K;
+ switch (adapter->hw.mac_type) {
+ case e1000_82547:
+ pba = E1000_PBA_30K;
+ break;
+ case e1000_82573:
+ pba = E1000_PBA_12K;
+ break;
+ default:
+ pba = E1000_PBA_48K;
+ break;
+ }
+
+
+
+ if(adapter->hw.mac_type == e1000_82547) {
adapter->tx_fifo_head = 0;
adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
adapter->tx_fifo_size =
(E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
atomic_set(&adapter->tx_fifo_stall, 0);
}
+
E1000_WRITE_REG(&adapter->hw, PBA, pba);
/* flow control settings */
adapter->hw.fc_send_xon = 1;
adapter->hw.fc = adapter->hw.original_fc;
+ /* Allow time for pending master requests to run */
e1000_reset_hw(&adapter->hw);
if(adapter->hw.mac_type >= e1000_82544)
E1000_WRITE_REG(&adapter->hw, WUC, 0);
if(e1000_init_hw(&adapter->hw))
DPRINTK(PROBE, ERR, "Hardware Error\n");
-
+ e1000_update_mng_vlan(adapter);
/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE);
e1000_reset_adaptive(&adapter->hw);
e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+ if (adapter->en_mng_pt) {
+ manc = E1000_READ_REG(&adapter->hw, MANC);
+ manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST);
+ E1000_WRITE_REG(&adapter->hw, MANC, manc);
+ }
}
/**
{
struct net_device *netdev;
struct e1000_adapter *adapter;
+ unsigned long mmio_start, mmio_len;
+ uint32_t swsm;
+
static int cards_found = 0;
- unsigned long mmio_start;
- int mmio_len;
- int pci_using_dac;
- int i;
- int err;
+ int i, err, pci_using_dac;
uint16_t eeprom_data;
uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
-
if((err = pci_enable_device(pdev)))
return err;
if((err = e1000_sw_init(adapter)))
goto err_sw_init;
+ if((err = e1000_check_phy_reset_block(&adapter->hw)))
+ DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
+
if(adapter->hw.mac_type >= e1000_82543) {
netdev->features = NETIF_F_SG |
NETIF_F_HW_CSUM |
if((adapter->hw.mac_type >= e1000_82544) &&
(adapter->hw.mac_type != e1000_82547))
netdev->features |= NETIF_F_TSO;
+
+#ifdef NETIF_F_TSO_IPV6
+ if(adapter->hw.mac_type > e1000_82547_rev_2)
+ netdev->features |= NETIF_F_TSO_IPV6;
+#endif
#endif
if(pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
/* hard_start_xmit is safe against parallel locking */
netdev->features |= NETIF_F_LLTX;
+ adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
+
/* before reading the EEPROM, reset the controller to
* put the device in a known good starting state */
/* reset the hardware with the new settings */
e1000_reset(adapter);
+ /* Let firmware know the driver has taken over */
+ switch(adapter->hw.mac_type) {
+ case e1000_82573:
+ swsm = E1000_READ_REG(&adapter->hw, SWSM);
+ E1000_WRITE_REG(&adapter->hw, SWSM,
+ swsm | E1000_SWSM_DRV_LOAD);
+ break;
+ default:
+ break;
+ }
+
strcpy(netdev->name, "eth%d");
if((err = register_netdev(netdev)))
goto err_register;
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
- uint32_t manc;
+ uint32_t manc, swsm;
flush_scheduled_work();
}
}
+ switch(adapter->hw.mac_type) {
+ case e1000_82573:
+ swsm = E1000_READ_REG(&adapter->hw, SWSM);
+ E1000_WRITE_REG(&adapter->hw, SWSM,
+ swsm & ~E1000_SWSM_DRV_LOAD);
+ break;
+
+ default:
+ break;
+ }
+
unregister_netdev(netdev);
- e1000_phy_hw_reset(&adapter->hw);
+ if(!e1000_check_phy_reset_block(&adapter->hw))
+ e1000_phy_hw_reset(&adapter->hw);
iounmap(adapter->hw.hw_addr);
pci_release_regions(pdev);
pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+ adapter->rx_ps_bsize0 = E1000_RXBUFFER_256;
hw->max_frame_size = netdev->mtu +
ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
/* initialize eeprom parameters */
- e1000_init_eeprom_params(hw);
+ if(e1000_init_eeprom_params(hw)) {
+ E1000_ERR("EEPROM initialization failed\n");
+ return -EIO;
+ }
switch(hw->mac_type) {
default:
if((err = e1000_up(adapter)))
goto err_up;
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+ if((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
+ e1000_update_mng_vlan(adapter);
+ }
return E1000_SUCCESS;
e1000_free_tx_resources(adapter);
e1000_free_rx_resources(adapter);
+ if((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
+ e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
+ }
return 0;
}
/**
* e1000_check_64k_bound - check that memory doesn't cross 64kB boundary
* @adapter: address of board private structure
- * @begin: address of beginning of memory
- * @end: address of end of memory
+ * @start: address of beginning of memory
+ * @len: length of memory
**/
static inline boolean_t
e1000_check_64k_bound(struct e1000_adapter *adapter,
{
struct e1000_desc_ring *rxdr = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
- int size;
+ int size, desc_len;
size = sizeof(struct e1000_buffer) * rxdr->count;
rxdr->buffer_info = vmalloc(size);
}
memset(rxdr->buffer_info, 0, size);
+ size = sizeof(struct e1000_ps_page) * rxdr->count;
+ rxdr->ps_page = kmalloc(size, GFP_KERNEL);
+ if(!rxdr->ps_page) {
+ vfree(rxdr->buffer_info);
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate memory for the receive descriptor ring\n");
+ return -ENOMEM;
+ }
+ memset(rxdr->ps_page, 0, size);
+
+ size = sizeof(struct e1000_ps_page_dma) * rxdr->count;
+ rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL);
+ if(!rxdr->ps_page_dma) {
+ vfree(rxdr->buffer_info);
+ kfree(rxdr->ps_page);
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate memory for the receive descriptor ring\n");
+ return -ENOMEM;
+ }
+ memset(rxdr->ps_page_dma, 0, size);
+
+ if(adapter->hw.mac_type <= e1000_82547_rev_2)
+ desc_len = sizeof(struct e1000_rx_desc);
+ else
+ desc_len = sizeof(union e1000_rx_desc_packet_split);
+
/* Round up to nearest 4K */
- rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
+ rxdr->size = rxdr->count * desc_len;
E1000_ROUNDUP(rxdr->size, 4096);
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
DPRINTK(PROBE, ERR,
"Unble to Allocate Memory for the Recieve descriptor ring\n");
vfree(rxdr->buffer_info);
+ kfree(rxdr->ps_page);
+ kfree(rxdr->ps_page_dma);
return -ENOMEM;
}
"Unable to Allocate aligned Memory for the"
" Receive descriptor ring\n");
vfree(rxdr->buffer_info);
+ kfree(rxdr->ps_page);
+ kfree(rxdr->ps_page_dma);
return -ENOMEM;
} else {
/* free old, move on with the new one since its okay */
static void
e1000_setup_rctl(struct e1000_adapter *adapter)
{
- uint32_t rctl;
+ uint32_t rctl, rfctl;
+ uint32_t psrctl = 0;
rctl = E1000_READ_REG(&adapter->hw, RCTL);
else
rctl &= ~E1000_RCTL_SBP;
+ if (adapter->netdev->mtu <= ETH_DATA_LEN)
+ rctl &= ~E1000_RCTL_LPE;
+ else
+ rctl |= E1000_RCTL_LPE;
+
/* Setup buffer sizes */
- rctl &= ~(E1000_RCTL_SZ_4096);
- rctl |= (E1000_RCTL_BSEX | E1000_RCTL_LPE);
- switch (adapter->rx_buffer_len) {
- case E1000_RXBUFFER_2048:
- default:
- rctl |= E1000_RCTL_SZ_2048;
- rctl &= ~(E1000_RCTL_BSEX | E1000_RCTL_LPE);
- break;
- case E1000_RXBUFFER_4096:
- rctl |= E1000_RCTL_SZ_4096;
- break;
- case E1000_RXBUFFER_8192:
- rctl |= E1000_RCTL_SZ_8192;
- break;
- case E1000_RXBUFFER_16384:
- rctl |= E1000_RCTL_SZ_16384;
- break;
+ if(adapter->hw.mac_type == e1000_82573) {
+ /* We can now specify buffers in 1K increments.
+ * BSIZE and BSEX are ignored in this case. */
+ rctl |= adapter->rx_buffer_len << 0x11;
+ } else {
+ rctl &= ~E1000_RCTL_SZ_4096;
+ rctl |= E1000_RCTL_BSEX;
+ switch (adapter->rx_buffer_len) {
+ case E1000_RXBUFFER_2048:
+ default:
+ rctl |= E1000_RCTL_SZ_2048;
+ rctl &= ~E1000_RCTL_BSEX;
+ break;
+ case E1000_RXBUFFER_4096:
+ rctl |= E1000_RCTL_SZ_4096;
+ break;
+ case E1000_RXBUFFER_8192:
+ rctl |= E1000_RCTL_SZ_8192;
+ break;
+ case E1000_RXBUFFER_16384:
+ rctl |= E1000_RCTL_SZ_16384;
+ break;
+ }
+ }
+
+#ifdef CONFIG_E1000_PACKET_SPLIT
+ /* 82571 and greater support packet-split where the protocol
+ * header is placed in skb->data and the packet data is
+ * placed in pages hanging off of skb_shinfo(skb)->nr_frags.
+ * In the case of a non-split, skb->data is linearly filled,
+ * followed by the page buffers. Therefore, skb->data is
+ * sized to hold the largest protocol header.
+ */
+ adapter->rx_ps = (adapter->hw.mac_type > e1000_82547_rev_2)
+ && (adapter->netdev->mtu
+ < ((3 * PAGE_SIZE) + adapter->rx_ps_bsize0));
+#endif
+ if(adapter->rx_ps) {
+ /* Configure extra packet-split registers */
+ rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
+ rfctl |= E1000_RFCTL_EXTEN;
+ /* disable IPv6 packet split support */
+ rfctl |= E1000_RFCTL_IPV6_DIS;
+ E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
+
+ rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC;
+
+ psrctl |= adapter->rx_ps_bsize0 >>
+ E1000_PSRCTL_BSIZE0_SHIFT;
+ psrctl |= PAGE_SIZE >>
+ E1000_PSRCTL_BSIZE1_SHIFT;
+ psrctl |= PAGE_SIZE <<
+ E1000_PSRCTL_BSIZE2_SHIFT;
+ psrctl |= PAGE_SIZE <<
+ E1000_PSRCTL_BSIZE3_SHIFT;
+
+ E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl);
}
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
e1000_configure_rx(struct e1000_adapter *adapter)
{
uint64_t rdba = adapter->rx_ring.dma;
- uint32_t rdlen = adapter->rx_ring.count * sizeof(struct e1000_rx_desc);
- uint32_t rctl;
- uint32_t rxcsum;
+ uint32_t rdlen, rctl, rxcsum;
+
+ if(adapter->rx_ps) {
+ rdlen = adapter->rx_ring.count *
+ sizeof(union e1000_rx_desc_packet_split);
+ adapter->clean_rx = e1000_clean_rx_irq_ps;
+ adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps;
+ } else {
+ rdlen = adapter->rx_ring.count * sizeof(struct e1000_rx_desc);
+ adapter->clean_rx = e1000_clean_rx_irq;
+ adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
+ }
/* disable receives while setting up the descriptors */
rctl = E1000_READ_REG(&adapter->hw, RCTL);
E1000_WRITE_REG(&adapter->hw, RDT, 0);
/* Enable 82543 Receive Checksum Offload for TCP and UDP */
- if((adapter->hw.mac_type >= e1000_82543) &&
- (adapter->rx_csum == TRUE)) {
+ if(adapter->hw.mac_type >= e1000_82543) {
rxcsum = E1000_READ_REG(&adapter->hw, RXCSUM);
- rxcsum |= E1000_RXCSUM_TUOFL;
+ if(adapter->rx_csum == TRUE) {
+ rxcsum |= E1000_RXCSUM_TUOFL;
+
+ /* Enable 82573 IPv4 payload checksum for UDP fragments
+ * Must be used in conjunction with packet-split. */
+ if((adapter->hw.mac_type > e1000_82547_rev_2) &&
+ (adapter->rx_ps)) {
+ rxcsum |= E1000_RXCSUM_IPPCSE;
+ }
+ } else {
+ rxcsum &= ~E1000_RXCSUM_TUOFL;
+ /* don't need to clear IPPCSE as it defaults to 0 */
+ }
E1000_WRITE_REG(&adapter->hw, RXCSUM, rxcsum);
}
+ if (adapter->hw.mac_type == e1000_82573)
+ E1000_WRITE_REG(&adapter->hw, ERT, 0x0100);
+
/* Enable Receives */
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
}
vfree(rx_ring->buffer_info);
rx_ring->buffer_info = NULL;
+ kfree(rx_ring->ps_page);
+ rx_ring->ps_page = NULL;
+ kfree(rx_ring->ps_page_dma);
+ rx_ring->ps_page_dma = NULL;
pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
{
struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct e1000_buffer *buffer_info;
+ struct e1000_ps_page *ps_page;
+ struct e1000_ps_page_dma *ps_page_dma;
struct pci_dev *pdev = adapter->pdev;
unsigned long size;
- unsigned int i;
+ unsigned int i, j;
/* Free all the Rx ring sk_buffs */
for(i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
if(buffer_info->skb) {
-
+ ps_page = &rx_ring->ps_page[i];
+ ps_page_dma = &rx_ring->ps_page_dma[i];
pci_unmap_single(pdev,
buffer_info->dma,
buffer_info->length,
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
+
+ for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ if(!ps_page->ps_page[j]) break;
+ pci_unmap_single(pdev,
+ ps_page_dma->ps_page_dma[j],
+ PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ ps_page_dma->ps_page_dma[j] = 0;
+ put_page(ps_page->ps_page[j]);
+ ps_page->ps_page[j] = NULL;
+ }
}
}
size = sizeof(struct e1000_buffer) * rx_ring->count;
memset(rx_ring->buffer_info, 0, size);
+ size = sizeof(struct e1000_ps_page) * rx_ring->count;
+ memset(rx_ring->ps_page, 0, size);
+ size = sizeof(struct e1000_ps_page_dma) * rx_ring->count;
+ memset(rx_ring->ps_page_dma, 0, size);
/* Zero out the descriptor ring */
uint32_t link;
e1000_check_for_link(&adapter->hw);
+ if (adapter->hw.mac_type == e1000_82573) {
+ e1000_enable_tx_pkt_filtering(&adapter->hw);
+ if(adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
+ e1000_update_mng_vlan(adapter);
+ }
if((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
!(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE))
#define E1000_TX_FLAGS_CSUM 0x00000001
#define E1000_TX_FLAGS_VLAN 0x00000002
#define E1000_TX_FLAGS_TSO 0x00000004
+#define E1000_TX_FLAGS_IPV4 0x00000008
#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000
#define E1000_TX_FLAGS_VLAN_SHIFT 16
struct e1000_context_desc *context_desc;
unsigned int i;
uint32_t cmd_length = 0;
- uint16_t ipcse, tucse, mss;
+ uint16_t ipcse = 0, tucse, mss;
uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
int err;
hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
mss = skb_shinfo(skb)->tso_size;
- skb->nh.iph->tot_len = 0;
- skb->nh.iph->check = 0;
- skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
- skb->nh.iph->daddr,
- 0,
- IPPROTO_TCP,
- 0);
+ if(skb->protocol == ntohs(ETH_P_IP)) {
+ skb->nh.iph->tot_len = 0;
+ skb->nh.iph->check = 0;
+ skb->h.th->check =
+ ~csum_tcpudp_magic(skb->nh.iph->saddr,
+ skb->nh.iph->daddr,
+ 0,
+ IPPROTO_TCP,
+ 0);
+ cmd_length = E1000_TXD_CMD_IP;
+ ipcse = skb->h.raw - skb->data - 1;
+#ifdef NETIF_F_TSO_IPV6
+ } else if(skb->protocol == ntohs(ETH_P_IPV6)) {
+ skb->nh.ipv6h->payload_len = 0;
+ skb->h.th->check =
+ ~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
+ &skb->nh.ipv6h->daddr,
+ 0,
+ IPPROTO_TCP,
+ 0);
+ ipcse = 0;
+#endif
+ }
ipcss = skb->nh.raw - skb->data;
ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data;
- ipcse = skb->h.raw - skb->data - 1;
tucss = skb->h.raw - skb->data;
tucso = (void *)&(skb->h.th->check) - (void *)skb->data;
tucse = 0;
cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
- E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP |
- (skb->len - (hdr_len)));
+ E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
i = adapter->tx_ring.next_to_use;
context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
if(likely(tx_flags & E1000_TX_FLAGS_TSO)) {
txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
E1000_TXD_CMD_TSE;
- txd_upper |= (E1000_TXD_POPTS_IXSM | E1000_TXD_POPTS_TXSM) << 8;
+ txd_upper |= E1000_TXD_POPTS_TXSM << 8;
+
+ if(likely(tx_flags & E1000_TX_FLAGS_IPV4))
+ txd_upper |= E1000_TXD_POPTS_IXSM << 8;
}
if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
return 0;
}
+#define MINIMUM_DHCP_PACKET_SIZE 282
+static inline int
+e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ uint16_t length, offset;
+ if(vlan_tx_tag_present(skb)) {
+ if(!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
+ ( adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
+ return 0;
+ }
+ if(htons(ETH_P_IP) == skb->protocol) {
+ const struct iphdr *ip = skb->nh.iph;
+ if(IPPROTO_UDP == ip->protocol) {
+ struct udphdr *udp = (struct udphdr *)(skb->h.uh);
+ if(ntohs(udp->dest) == 67) {
+ offset = (uint8_t *)udp + 8 - skb->data;
+ length = skb->len - offset;
+
+ return e1000_mng_write_dhcp_info(hw,
+ (uint8_t *)udp + 8, length);
+ }
+ }
+ } else if((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
+ struct ethhdr *eth = (struct ethhdr *) skb->data;
+ if((htons(ETH_P_IP) == eth->h_proto)) {
+ const struct iphdr *ip =
+ (struct iphdr *)((uint8_t *)skb->data+14);
+ if(IPPROTO_UDP == ip->protocol) {
+ struct udphdr *udp =
+ (struct udphdr *)((uint8_t *)ip +
+ (ip->ihl << 2));
+ if(ntohs(udp->dest) == 67) {
+ offset = (uint8_t *)udp + 8 - skb->data;
+ length = skb->len - offset;
+
+ return e1000_mng_write_dhcp_info(hw,
+ (uint8_t *)udp + 8,
+ length);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
static int
e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
local_irq_restore(flags);
return NETDEV_TX_LOCKED;
}
+ if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
+ e1000_transfer_dhcp_info(adapter, skb);
+
/* need: count + 2 desc gap to keep tail from touching
* head, otherwise try next time */
else if(likely(e1000_tx_csum(adapter, skb)))
tx_flags |= E1000_TX_FLAGS_CSUM;
+ /* Old method was to assume IPv4 packet by default if TSO was enabled.
+ * 82573 hardware supports TSO capabilities for IPv6 as well...
+ * no longer assume, we must. */
+ if(likely(skb->protocol == ntohs(ETH_P_IP)))
+ tx_flags |= E1000_TX_FLAGS_IPV4;
+
e1000_tx_queue(adapter,
e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss),
tx_flags);
e1000_change_mtu(struct net_device *netdev, int new_mtu)
{
struct e1000_adapter *adapter = netdev->priv;
- int old_mtu = adapter->rx_buffer_len;
int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
return -EINVAL;
}
- if(max_frame <= MAXIMUM_ETHERNET_FRAME_SIZE) {
- adapter->rx_buffer_len = E1000_RXBUFFER_2048;
-
- } else if(adapter->hw.mac_type < e1000_82543) {
- DPRINTK(PROBE, ERR, "Jumbo Frames not supported on 82542\n");
+#define MAX_STD_JUMBO_FRAME_SIZE 9216
+ /* might want this to be bigger enum check... */
+ if (adapter->hw.mac_type == e1000_82573 &&
+ max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
+ DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
+ "on 82573\n");
return -EINVAL;
+ }
- } else if(max_frame <= E1000_RXBUFFER_4096) {
- adapter->rx_buffer_len = E1000_RXBUFFER_4096;
-
- } else if(max_frame <= E1000_RXBUFFER_8192) {
- adapter->rx_buffer_len = E1000_RXBUFFER_8192;
-
+ if(adapter->hw.mac_type > e1000_82547_rev_2) {
+ adapter->rx_buffer_len = max_frame;
+ E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
} else {
- adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+ if(unlikely((adapter->hw.mac_type < e1000_82543) &&
+ (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) {
+ DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
+ "on 82542\n");
+ return -EINVAL;
+
+ } else {
+ if(max_frame <= E1000_RXBUFFER_2048) {
+ adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+ } else if(max_frame <= E1000_RXBUFFER_4096) {
+ adapter->rx_buffer_len = E1000_RXBUFFER_4096;
+ } else if(max_frame <= E1000_RXBUFFER_8192) {
+ adapter->rx_buffer_len = E1000_RXBUFFER_8192;
+ } else if(max_frame <= E1000_RXBUFFER_16384) {
+ adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+ }
+ }
}
- if(old_mtu != adapter->rx_buffer_len && netif_running(netdev)) {
+ netdev->mtu = new_mtu;
+
+ if(netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
}
- netdev->mtu = new_mtu;
adapter->hw.max_frame_size = max_frame;
return 0;
adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
}
+ if(hw->mac_type > e1000_82547_rev_2) {
+ adapter->stats.iac += E1000_READ_REG(hw, IAC);
+ adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
+ adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
+ adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC);
+ adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC);
+ adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC);
+ adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC);
+ adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC);
+ adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC);
+ }
/* Fill out the OS statistics structure */
}
for(i = 0; i < E1000_MAX_INTR; i++)
- if(unlikely(!e1000_clean_rx_irq(adapter) &
+ if(unlikely(!adapter->clean_rx(adapter) &
!e1000_clean_tx_irq(adapter)))
break;
int work_done = 0;
tx_cleaned = e1000_clean_tx_irq(adapter);
- e1000_clean_rx_irq(adapter, &work_done, work_to_do);
+ adapter->clean_rx(adapter, &work_done, work_to_do);
*budget -= work_done;
netdev->quota -= work_done;
/**
* e1000_rx_checksum - Receive Checksum Offload for 82543
- * @adapter: board private structure
- * @rx_desc: receive descriptor
- * @sk_buff: socket buffer with received data
+ * @adapter: board private structure
+ * @status_err: receive descriptor status and error fields
+ * @csum: receive descriptor csum field
+ * @sk_buff: socket buffer with received data
**/
static inline void
e1000_rx_checksum(struct e1000_adapter *adapter,
- struct e1000_rx_desc *rx_desc,
- struct sk_buff *skb)
+ uint32_t status_err, uint32_t csum,
+ struct sk_buff *skb)
{
+ uint16_t status = (uint16_t)status_err;
+ uint8_t errors = (uint8_t)(status_err >> 24);
+ skb->ip_summed = CHECKSUM_NONE;
+
/* 82543 or newer only */
- if(unlikely((adapter->hw.mac_type < e1000_82543) ||
+ if(unlikely(adapter->hw.mac_type < e1000_82543)) return;
/* Ignore Checksum bit is set */
- (rx_desc->status & E1000_RXD_STAT_IXSM) ||
- /* TCP Checksum has not been calculated */
- (!(rx_desc->status & E1000_RXD_STAT_TCPCS)))) {
- skb->ip_summed = CHECKSUM_NONE;
- return;
- }
-
- /* At this point we know the hardware did the TCP checksum */
- /* now look at the TCP checksum error bit */
- if(rx_desc->errors & E1000_RXD_ERR_TCPE) {
+ if(unlikely(status & E1000_RXD_STAT_IXSM)) return;
+ /* TCP/UDP checksum error bit is set */
+ if(unlikely(errors & E1000_RXD_ERR_TCPE)) {
/* let the stack verify checksum errors */
- skb->ip_summed = CHECKSUM_NONE;
adapter->hw_csum_err++;
+ return;
+ }
+ /* TCP/UDP Checksum has not been calculated */
+ if(adapter->hw.mac_type <= e1000_82547_rev_2) {
+ if(!(status & E1000_RXD_STAT_TCPCS))
+ return;
} else {
+ if(!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
+ return;
+ }
+ /* It must be a TCP or UDP packet with a valid checksum */
+ if (likely(status & E1000_RXD_STAT_TCPCS)) {
/* TCP checksum is good */
skb->ip_summed = CHECKSUM_UNNECESSARY;
- adapter->hw_csum_good++;
+ } else if (adapter->hw.mac_type > e1000_82547_rev_2) {
+ /* IP fragment with UDP payload */
+ /* Hardware complements the payload checksum, so we undo it
+ * and then put the value in host order for further stack use.
+ */
+ csum = ntohl(csum ^ 0xFFFF);
+ skb->csum = csum;
+ skb->ip_summed = CHECKSUM_HW;
}
+ adapter->hw_csum_good++;
}
/**
- * e1000_clean_rx_irq - Send received data up the network stack
+ * e1000_clean_rx_irq - Send received data up the network stack; legacy
* @adapter: board private structure
**/
skb_put(skb, length - ETHERNET_FCS_SIZE);
/* Receive Checksum Offload */
- e1000_rx_checksum(adapter, rx_desc, skb);
-
+ e1000_rx_checksum(adapter,
+ (uint32_t)(rx_desc->status) |
+ ((uint32_t)(rx_desc->errors) << 24),
+ rx_desc->csum, skb);
skb->protocol = eth_type_trans(skb, netdev);
#ifdef CONFIG_E1000_NAPI
if(unlikely(adapter->vlgrp &&
(rx_desc->status & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->special) &
- E1000_RXD_SPC_VLAN_MASK);
+ le16_to_cpu(rx_desc->special) &
+ E1000_RXD_SPC_VLAN_MASK);
} else {
netif_receive_skb(skb);
}
rx_desc = E1000_RX_DESC(*rx_ring, i);
}
-
rx_ring->next_to_clean = i;
+ adapter->alloc_rx_buf(adapter);
+
+ return cleaned;
+}
+
+/**
+ * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split
+ * @adapter: board private structure
+ **/
+
+static boolean_t
+#ifdef CONFIG_E1000_NAPI
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, int *work_done,
+ int work_to_do)
+#else
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
+#endif
+{
+ struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+ union e1000_rx_desc_packet_split *rx_desc;
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ struct e1000_buffer *buffer_info;
+ struct e1000_ps_page *ps_page;
+ struct e1000_ps_page_dma *ps_page_dma;
+ struct sk_buff *skb;
+ unsigned int i, j;
+ uint32_t length, staterr;
+ boolean_t cleaned = FALSE;
+
+ i = rx_ring->next_to_clean;
+ rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+ staterr = rx_desc->wb.middle.status_error;
+
+ while(staterr & E1000_RXD_STAT_DD) {
+ buffer_info = &rx_ring->buffer_info[i];
+ ps_page = &rx_ring->ps_page[i];
+ ps_page_dma = &rx_ring->ps_page_dma[i];
+#ifdef CONFIG_E1000_NAPI
+ if(unlikely(*work_done >= work_to_do))
+ break;
+ (*work_done)++;
+#endif
+ cleaned = TRUE;
+ pci_unmap_single(pdev, buffer_info->dma,
+ buffer_info->length,
+ PCI_DMA_FROMDEVICE);
+
+ skb = buffer_info->skb;
+
+ if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
+ E1000_DBG("%s: Packet Split buffers didn't pick up"
+ " the full packet\n", netdev->name);
+ dev_kfree_skb_irq(skb);
+ goto next_desc;
+ }
- e1000_alloc_rx_buffers(adapter);
+ if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
+ dev_kfree_skb_irq(skb);
+ goto next_desc;
+ }
+
+ length = le16_to_cpu(rx_desc->wb.middle.length0);
+
+ if(unlikely(!length)) {
+ E1000_DBG("%s: Last part of the packet spanning"
+ " multiple descriptors\n", netdev->name);
+ dev_kfree_skb_irq(skb);
+ goto next_desc;
+ }
+
+ /* Good Receive */
+ skb_put(skb, length);
+
+ for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
+ break;
+
+ pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
+ PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ ps_page_dma->ps_page_dma[j] = 0;
+ skb_shinfo(skb)->frags[j].page =
+ ps_page->ps_page[j];
+ ps_page->ps_page[j] = NULL;
+ skb_shinfo(skb)->frags[j].page_offset = 0;
+ skb_shinfo(skb)->frags[j].size = length;
+ skb_shinfo(skb)->nr_frags++;
+ skb->len += length;
+ skb->data_len += length;
+ }
+
+ e1000_rx_checksum(adapter, staterr,
+ rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
+ skb->protocol = eth_type_trans(skb, netdev);
+
+#ifdef HAVE_RX_ZERO_COPY
+ if(likely(rx_desc->wb.upper.header_status &
+ E1000_RXDPS_HDRSTAT_HDRSP))
+ skb_shinfo(skb)->zero_copy = TRUE;
+#endif
+#ifdef CONFIG_E1000_NAPI
+ if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+ vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
+ le16_to_cpu(rx_desc->wb.middle.vlan &
+ E1000_RXD_SPC_VLAN_MASK));
+ } else {
+ netif_receive_skb(skb);
+ }
+#else /* CONFIG_E1000_NAPI */
+ if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+ vlan_hwaccel_rx(skb, adapter->vlgrp,
+ le16_to_cpu(rx_desc->wb.middle.vlan &
+ E1000_RXD_SPC_VLAN_MASK));
+ } else {
+ netif_rx(skb);
+ }
+#endif /* CONFIG_E1000_NAPI */
+ netdev->last_rx = jiffies;
+
+next_desc:
+ rx_desc->wb.middle.status_error &= ~0xFF;
+ buffer_info->skb = NULL;
+ if(unlikely(++i == rx_ring->count)) i = 0;
+
+ rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+ staterr = rx_desc->wb.middle.status_error;
+ }
+ rx_ring->next_to_clean = i;
+ adapter->alloc_rx_buf(adapter);
return cleaned;
}
/**
- * e1000_alloc_rx_buffers - Replace used receive buffers
+ * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
* @adapter: address of board private structure
**/
rx_ring->next_to_use = i;
}
+/**
+ * e1000_alloc_rx_buffers_ps - Replace used receive buffers; packet split
+ * @adapter: address of board private structure
+ **/
+
+static void
+e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
+{
+ struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ union e1000_rx_desc_packet_split *rx_desc;
+ struct e1000_buffer *buffer_info;
+ struct e1000_ps_page *ps_page;
+ struct e1000_ps_page_dma *ps_page_dma;
+ struct sk_buff *skb;
+ unsigned int i, j;
+
+ i = rx_ring->next_to_use;
+ buffer_info = &rx_ring->buffer_info[i];
+ ps_page = &rx_ring->ps_page[i];
+ ps_page_dma = &rx_ring->ps_page_dma[i];
+
+ while(!buffer_info->skb) {
+ rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+
+ for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ if(unlikely(!ps_page->ps_page[j])) {
+ ps_page->ps_page[j] =
+ alloc_page(GFP_ATOMIC);
+ if(unlikely(!ps_page->ps_page[j]))
+ goto no_buffers;
+ ps_page_dma->ps_page_dma[j] =
+ pci_map_page(pdev,
+ ps_page->ps_page[j],
+ 0, PAGE_SIZE,
+ PCI_DMA_FROMDEVICE);
+ }
+ /* Refresh the desc even if buffer_addrs didn't
+ * change because each write-back erases this info.
+ */
+ rx_desc->read.buffer_addr[j+1] =
+ cpu_to_le64(ps_page_dma->ps_page_dma[j]);
+ }
+
+ skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
+
+ if(unlikely(!skb))
+ break;
+
+ /* Make buffer alignment 2 beyond a 16 byte boundary
+ * this will result in a 16 byte aligned IP header after
+ * the 14 byte MAC header is removed
+ */
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ skb->dev = netdev;
+
+ buffer_info->skb = skb;
+ buffer_info->length = adapter->rx_ps_bsize0;
+ buffer_info->dma = pci_map_single(pdev, skb->data,
+ adapter->rx_ps_bsize0,
+ PCI_DMA_FROMDEVICE);
+
+ rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma);
+
+ if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) {
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64). */
+ wmb();
+ /* Hardware increments by 16 bytes, but packet split
+ * descriptors are 32 bytes...so we increment tail
+ * twice as much.
+ */
+ E1000_WRITE_REG(&adapter->hw, RDT, i<<1);
+ }
+
+ if(unlikely(++i == rx_ring->count)) i = 0;
+ buffer_info = &rx_ring->buffer_info[i];
+ ps_page = &rx_ring->ps_page[i];
+ ps_page_dma = &rx_ring->ps_page_dma[i];
+ }
+
+no_buffers:
+ rx_ring->next_to_use = i;
+}
+
/**
* e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers.
* @adapter:
rctl |= E1000_RCTL_VFE;
rctl &= ~E1000_RCTL_CFIEN;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ e1000_update_mng_vlan(adapter);
} else {
/* disable VLAN tag insert/strip */
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl &= ~E1000_RCTL_VFE;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
+ e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+ }
}
e1000_irq_enable(adapter);
{
struct e1000_adapter *adapter = netdev->priv;
uint32_t vfta, index;
-
+ if((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+ (vid == adapter->mng_vlan_id))
+ return;
/* add VID to filter table */
index = (vid >> 5) & 0x7F;
vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
e1000_irq_enable(adapter);
+ if((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+ (vid == adapter->mng_vlan_id))
+ return;
/* remove VID from filter table */
index = (vid >> 5) & 0x7F;
vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
- uint32_t ctrl, ctrl_ext, rctl, manc, status;
+ uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm;
uint32_t wufc = adapter->wol;
netif_device_detach(netdev);
E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext);
}
+ /* Allow time for pending master requests to run */
+ e1000_disable_pciex_master(&adapter->hw);
+
E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
pci_enable_wake(pdev, 3, 1);
}
}
+ switch(adapter->hw.mac_type) {
+ case e1000_82573:
+ swsm = E1000_READ_REG(&adapter->hw, SWSM);
+ E1000_WRITE_REG(&adapter->hw, SWSM,
+ swsm & ~E1000_SWSM_DRV_LOAD);
+ break;
+ default:
+ break;
+ }
+
pci_disable_device(pdev);
state = (state > 0) ? 3 : 0;
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
- uint32_t manc, ret;
+ uint32_t manc, ret, swsm;
pci_set_power_state(pdev, 0);
pci_restore_state(pdev);
E1000_WRITE_REG(&adapter->hw, MANC, manc);
}
+ switch(adapter->hw.mac_type) {
+ case e1000_82573:
+ swsm = E1000_READ_REG(&adapter->hw, SWSM);
+ E1000_WRITE_REG(&adapter->hw, SWSM,
+ swsm | E1000_SWSM_DRV_LOAD);
+ break;
+ default:
+ break;
+ }
+
return 0;
}
#endif
-
#ifdef CONFIG_NET_POLL_CONTROLLER
/*
* Polling 'interrupt' - used by things like netconsole to send skbs
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##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_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_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_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
+ readb((a)->hw_addr + \
+ (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
+ (offset)))
+
#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS)
#endif /* _E1000_OSDEP_H_ */