summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortackerman <tackerman@FreeBSD.org>2005-05-26 23:32:02 +0000
committertackerman <tackerman@FreeBSD.org>2005-05-26 23:32:02 +0000
commit8b2ddc8fab4a5de9a367f9558a299aaad666f51d (patch)
tree8f8a3567ee38bb6bee585911878c9c8323a25a57
parentd155c550d1053d5c4d1b91ce5db80722c772590d (diff)
downloadFreeBSD-src-8b2ddc8fab4a5de9a367f9558a299aaad666f51d.zip
FreeBSD-src-8b2ddc8fab4a5de9a367f9558a299aaad666f51d.tar.gz
Changes to update driver with latest Intel driver version 2.1.7
- Changed from using explicit devices id to using descriptive labels. - Added support for 82573 and 82546 Quad adapters. - Corrected support for 82547EI and 82541ER (mac_type was not assigned) - Removed #ifdef DBG_STATS and extraneous code. if_em_hw.c/if_em_hw.h - Added support for 82573 and 82546 Quad adapters. - Brought forward Intel's most current mac and phy changes.
-rw-r--r--sys/dev/em/if_em.c103
-rw-r--r--sys/dev/em/if_em.h7
-rw-r--r--sys/dev/em/if_em_hw.c2316
-rw-r--r--sys/dev/em/if_em_hw.h586
-rw-r--r--sys/dev/em/if_em_osdep.h21
5 files changed, 2504 insertions, 529 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c
index 32a433f..4e9d282 100644
--- a/sys/dev/em/if_em.c
+++ b/sys/dev/em/if_em.c
@@ -1,6 +1,6 @@
/**************************************************************************
-Copyright (c) 2001-2003, Intel Corporation
+Copyright (c) 2001-2005, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -51,7 +51,7 @@ struct adapter *em_adapter_list = NULL;
* Driver version
*********************************************************************/
-char em_driver_version[] = "1.7.35";
+char em_driver_version[] = "2.1.7";
/*********************************************************************
@@ -67,40 +67,52 @@ char em_driver_version[] = "1.7.35";
static em_vendor_info_t em_vendor_info_array[] =
{
/* Intel(R) PRO/1000 Network Connection */
- { 0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1008, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1009, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x100C, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x100F, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1010, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1014, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1015, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1018, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x101A, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1026, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1027, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1028, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1075, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1076, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1077, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1078, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x1079, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x107A, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x107B, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x107C, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, 0x108A, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82540EM, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82540EM_LOM, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82540EP, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82540EP_LOM, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82540EP_LP, PCI_ANY_ID, PCI_ANY_ID, 0},
+
+ { 0x8086, E1000_DEV_ID_82541EI, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82541ER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82541ER_LOM, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82541EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82541GI, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82541GI_LF, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82541GI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0},
+
+ { 0x8086, E1000_DEV_ID_82542, PCI_ANY_ID, PCI_ANY_ID, 0},
+
+ { 0x8086, E1000_DEV_ID_82543GC_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82543GC_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+
+ { 0x8086, E1000_DEV_ID_82544EI_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82544EI_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82544GC_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82544GC_LOM, PCI_ANY_ID, PCI_ANY_ID, 0},
+
+ { 0x8086, E1000_DEV_ID_82545EM_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82545EM_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82545GM_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82545GM_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82545GM_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
+
+ { 0x8086, E1000_DEV_ID_82546EB_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82546EB_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82546EB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82546GB_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82546GB_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82546GB_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82546GB_PCIE, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+
+ { 0x8086, E1000_DEV_ID_82547EI, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82547EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82547GI, PCI_ANY_ID, PCI_ANY_ID, 0},
+
+ { 0x8086, E1000_DEV_ID_82573E, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82573E_IAMT, PCI_ANY_ID, PCI_ANY_ID, 0},
+
/* required last entry */
{ 0, 0, 0, 0, 0}
};
@@ -666,7 +678,9 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
break;
case SIOCSIFMTU:
IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)");
- if (ifr->ifr_mtu > MAX_JUMBO_FRAME_SIZE - ETHER_HDR_LEN) {
+ if (ifr->ifr_mtu > MAX_JUMBO_FRAME_SIZE - ETHER_HDR_LEN || \
+ /* 82573 does not support jumbo frames */
+ (adapter->hw.mac_type == em_82573 && ifr->ifr_mtu > ETHERMTU) ) {
error = EINVAL;
} else {
EM_LOCK(adapter);
@@ -2259,6 +2273,8 @@ em_initialize_transmit_unit(struct adapter * adapter)
/* Program the Transmit Control Register */
reg_tctl = E1000_TCTL_PSP | E1000_TCTL_EN |
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
+ if (adapter->hw.mac_type >= em_82573)
+ reg_tctl |= E1000_TCTL_MULR;
if (adapter->link_duplex == 1) {
reg_tctl |= E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT;
} else {
@@ -2416,9 +2432,6 @@ em_clean_transmit_interrupts(struct adapter * adapter)
if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
return;
-#ifdef DBG_STATS
- adapter->clean_tx_interrupts++;
-#endif
num_avail = adapter->num_tx_desc_avail;
i = adapter->oldest_used_tx_desc;
@@ -2779,9 +2792,6 @@ em_process_receive_interrupts(struct adapter * adapter, int count)
BUS_DMASYNC_POSTREAD);
if (!((current_desc->status) & E1000_RXD_STAT_DD)) {
-#ifdef DBG_STATS
- adapter->no_pkts_avail++;
-#endif
return;
}
@@ -3274,13 +3284,6 @@ em_print_debug_info(struct adapter *adapter)
printf("em%d:rx_int_delay = %d, rx_abs_int_delay = %d\n", unit,
E1000_READ_REG(&adapter->hw, RDTR),
E1000_READ_REG(&adapter->hw, RADV));
-
-#ifdef DBG_STATS
- printf("em%d: Packets not Avail = %ld\n", unit,
- adapter->no_pkts_avail);
- printf("em%d: CleanTxInterrupts = %ld\n", unit,
- adapter->clean_tx_interrupts);
-#endif
printf("em%d: fifo workaround = %lld, fifo_reset = %lld\n", unit,
(long long)adapter->tx_fifo_wrk_cnt,
(long long)adapter->tx_fifo_reset_cnt);
diff --git a/sys/dev/em/if_em.h b/sys/dev/em/if_em.h
index 41b46c8..38399ea 100644
--- a/sys/dev/em/if_em.h
+++ b/sys/dev/em/if_em.h
@@ -1,6 +1,6 @@
/**************************************************************************
-Copyright (c) 2001-2003, Intel Corporation
+Copyright (c) 2001-2005, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -422,11 +422,6 @@ struct adapter {
boolean_t pcix_82544;
boolean_t in_detach;
-#ifdef DBG_STATS
- unsigned long no_pkts_avail;
- unsigned long clean_tx_interrupts;
-
-#endif
struct em_hw_stats stats;
};
diff --git a/sys/dev/em/if_em_hw.c b/sys/dev/em/if_em_hw.c
index ee3be59..8795f6d 100644
--- a/sys/dev/em/if_em_hw.c
+++ b/sys/dev/em/if_em_hw.c
@@ -1,6 +1,6 @@
/*******************************************************************************
- Copyright (c) 2001-2003, Intel Corporation
+ Copyright (c) 2001-2005, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -71,9 +71,11 @@ static uint16_t em_shift_in_ee_bits(struct em_hw *hw, uint16_t count);
static int32_t em_acquire_eeprom(struct em_hw *hw);
static void em_release_eeprom(struct em_hw *hw);
static void em_standby_eeprom(struct em_hw *hw);
-static int32_t em_id_led_init(struct em_hw * hw);
static int32_t em_set_vco_speed(struct em_hw *hw);
+static int32_t em_polarity_reversal_workaround(struct em_hw *hw);
static int32_t em_set_phy_mode(struct em_hw *hw);
+static int32_t em_host_if_read_cookie(struct em_hw *hw, uint8_t *buffer);
+static uint8_t em_calculate_mng_checksum(char *buffer, uint32_t length);
/* IGP cable length table */
static const
@@ -87,6 +89,17 @@ uint16_t em_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
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 em_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.
@@ -98,10 +111,14 @@ em_set_phy_type(struct em_hw *hw)
{
DEBUGFUNC("em_set_phy_type");
+ if(hw->mac_type == em_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 = em_phy_m88;
break;
case IGP01E1000_I_PHY_ID:
@@ -130,16 +147,30 @@ em_set_phy_type(struct em_hw *hw)
static void
em_phy_init_script(struct em_hw *hw)
{
+ uint32_t ret_val;
+ uint16_t phy_saved_data;
+
DEBUGFUNC("em_phy_init_script");
if(hw->phy_init_script) {
msec_delay(20);
+ /* Save off the current value of register 0x2F5B to be restored at
+ * the end of this routine. */
+ ret_val = em_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
+
+ /* Disabled the PHY transmitter */
+ em_write_phy_reg(hw, 0x2F5B, 0x0003);
+
+ msec_delay(20);
+
em_write_phy_reg(hw,0x0000,0x0140);
msec_delay(5);
- if(hw->mac_type == em_82541 || hw->mac_type == em_82547) {
+ switch(hw->mac_type) {
+ case em_82541:
+ case em_82547:
em_write_phy_reg(hw, 0x1F95, 0x0001);
em_write_phy_reg(hw, 0x1F71, 0xBD21);
@@ -157,12 +188,23 @@ em_phy_init_script(struct em_hw *hw)
em_write_phy_reg(hw, 0x1F96, 0x003F);
em_write_phy_reg(hw, 0x2010, 0x0008);
- } else {
+ break;
+
+ case em_82541_rev_2:
+ case em_82547_rev_2:
em_write_phy_reg(hw, 0x1F73, 0x0099);
+ break;
+ default:
+ break;
}
em_write_phy_reg(hw, 0x0000, 0x3300);
+ msec_delay(20);
+
+ /* Now enable the transmitter */
+ em_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+
if(hw->mac_type == em_82547) {
uint16_t fused, fine, coarse;
@@ -251,9 +293,12 @@ em_set_mac_type(struct em_hw *hw)
case E1000_DEV_ID_82546GB_COPPER:
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 = em_82546_rev_3;
break;
case E1000_DEV_ID_82541EI:
+ case E1000_DEV_ID_82541ER_LOM:
case E1000_DEV_ID_82541EI_MOBILE:
hw->mac_type = em_82541;
break;
@@ -264,16 +309,35 @@ em_set_mac_type(struct em_hw *hw)
hw->mac_type = em_82541_rev_2;
break;
case E1000_DEV_ID_82547EI:
+ case E1000_DEV_ID_82547EI_MOBILE:
hw->mac_type = em_82547;
break;
case E1000_DEV_ID_82547GI:
hw->mac_type = em_82547_rev_2;
break;
+ case E1000_DEV_ID_82573E:
+ case E1000_DEV_ID_82573E_IAMT:
+ hw->mac_type = em_82573;
+ break;
default:
/* Should never have loaded on this device */
return -E1000_ERR_MAC_TYPE;
}
+ switch(hw->mac_type) {
+ case em_82573:
+ hw->eeprom_semaphore_present = TRUE;
+ /* fall through */
+ case em_82541:
+ case em_82547:
+ case em_82541_rev_2:
+ case em_82547_rev_2:
+ hw->asf_firmware_present = TRUE;
+ break;
+ default:
+ break;
+ }
+
return E1000_SUCCESS;
}
@@ -329,6 +393,9 @@ em_reset_hw(struct em_hw *hw)
uint32_t icr;
uint32_t manc;
uint32_t led_ctrl;
+ uint32_t timeout;
+ uint32_t extcnf_ctrl;
+ int32_t ret_val;
DEBUGFUNC("em_reset_hw");
@@ -338,6 +405,15 @@ em_reset_hw(struct em_hw *hw)
em_pci_clear_mwi(hw);
}
+ if(hw->bus_type == em_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(em_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);
@@ -362,10 +438,32 @@ em_reset_hw(struct em_hw *hw)
/* Must reset the PHY before resetting the MAC */
if((hw->mac_type == em_82541) || (hw->mac_type == em_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 == em_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-
@@ -421,6 +519,18 @@ em_reset_hw(struct em_hw *hw)
/* Wait for EEPROM reload */
msec_delay(20);
break;
+ case em_82573:
+ usec_delay(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 = em_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);
@@ -428,7 +538,7 @@ em_reset_hw(struct em_hw *hw)
}
/* Disable HW ARPs on ASF enabled adapters */
- if(hw->mac_type >= em_82540) {
+ if(hw->mac_type >= em_82540 && hw->mac_type <= em_82547_rev_2) {
manc = E1000_READ_REG(hw, MANC);
manc &= ~(E1000_MANC_ARP_EN);
E1000_WRITE_REG(hw, MANC, manc);
@@ -481,6 +591,8 @@ em_init_hw(struct em_hw *hw)
uint16_t pcix_stat_hi_word;
uint16_t cmd_mmrbc;
uint16_t stat_mmrbc;
+ uint32_t mta_size;
+
DEBUGFUNC("em_init_hw");
/* Initialize Identification LED */
@@ -495,8 +607,8 @@ em_init_hw(struct em_hw *hw)
/* Disabling VLAN filtering. */
DEBUGOUT("Initializing the IEEE VLAN\n");
- E1000_WRITE_REG(hw, VET, 0);
-
+ if (hw->mac_type < em_82545_rev_3)
+ E1000_WRITE_REG(hw, VET, 0);
em_clear_vfta(hw);
/* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
@@ -524,14 +636,16 @@ em_init_hw(struct em_hw *hw)
/* 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 <= em_82543) {
ctrl = E1000_READ_REG(hw, CTRL);
E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR);
}
@@ -569,9 +683,21 @@ em_init_hw(struct em_hw *hw)
if(hw->mac_type > em_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 em_82573:
+ ctrl |= E1000_TXDCTL_COUNT_DESC;
+ break;
+ }
E1000_WRITE_REG(hw, TXDCTL, ctrl);
}
+ if (hw->mac_type == em_82573) {
+ em_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
@@ -650,7 +776,7 @@ em_setup_link(struct em_hw *hw)
* control setting, then the variable hw->fc will
* be initialized based on a value in the EEPROM.
*/
- if(em_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data) < 0) {
+ if(em_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data)) {
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
@@ -707,6 +833,7 @@ em_setup_link(struct em_hw *hw)
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,
@@ -877,20 +1004,18 @@ em_setup_fiber_serdes_link(struct em_hw *hw)
}
/******************************************************************************
-* 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
-em_setup_copper_link(struct em_hw *hw)
+em_copper_link_preconfig(struct em_hw *hw)
{
uint32_t ctrl;
- uint32_t led_ctrl;
int32_t ret_val;
- uint16_t i;
uint16_t phy_data;
- DEBUGFUNC("em_setup_copper_link");
+ DEBUGFUNC("em_copper_link_preconfig");
ctrl = E1000_READ_REG(hw, CTRL);
/* With 82543, we need to force speed and duplex on the MAC equal to what
@@ -904,7 +1029,9 @@ em_setup_copper_link(struct em_hw *hw)
} else {
ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
E1000_WRITE_REG(hw, CTRL, ctrl);
- em_phy_hw_reset(hw);
+ ret_val = em_phy_hw_reset(hw);
+ if(ret_val)
+ return ret_val;
}
/* Make sure we have a valid PHY */
@@ -932,274 +1059,398 @@ em_setup_copper_link(struct em_hw *hw)
hw->mac_type == em_82541_rev_2 || hw->mac_type == em_82547_rev_2)
hw->phy_reset_disable = FALSE;
- if(!hw->phy_reset_disable) {
- if (hw->phy_type == em_phy_igp) {
+ return E1000_SUCCESS;
+}
- ret_val = em_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);
+/********************************************************************
+* Copper link setup for em_phy_igp series.
+*
+* hw - Struct containing variables accessed by shared code
+*********************************************************************/
+static int32_t
+em_copper_link_igp_setup(struct em_hw *hw)
+{
+ uint32_t led_ctrl;
+ int32_t ret_val;
+ uint16_t phy_data;
- /* 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);
+ DEBUGFUNC("em_copper_link_igp_setup");
- /* disable lplu d3 during driver init */
- ret_val = em_set_d3_lplu_state(hw, FALSE);
- if(ret_val) {
- DEBUGOUT("Error Disabling LPLU D3\n");
- return ret_val;
- }
+ if (hw->phy_reset_disable)
+ return E1000_SUCCESS;
+
+ ret_val = em_phy_reset(hw);
+ if (ret_val) {
+ DEBUGOUT("Error Resetting the PHY\n");
+ return ret_val;
+ }
- /* Configure mdi-mdix settings */
- ret_val = em_read_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);
- if((hw->mac_type == em_82541) || (hw->mac_type == em_82547)) {
- hw->dsp_config_state = em_dsp_config_disabled;
- /* Force MDI for IGP B-0 PHY */
- phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX |
- IGP01E1000_PSCR_FORCE_MDI_MDIX);
- hw->mdix = 1;
+ /* 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);
- } else {
- hw->dsp_config_state = em_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 = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
- phy_data);
- if(ret_val)
- return ret_val;
+ /* disable lplu d3 during driver init */
+ ret_val = em_set_d3_lplu_state(hw, FALSE);
+ if (ret_val) {
+ DEBUGOUT("Error Disabling LPLU D3\n");
+ return ret_val;
+ }
- /* set auto-master slave resolution settings */
- if(hw->autoneg) {
- em_ms_type phy_ms_setting = hw->master_slave;
+ /* disable lplu d0 during driver init */
+ ret_val = em_set_d0_lplu_state(hw, FALSE);
+ if (ret_val) {
+ DEBUGOUT("Error Disabling LPLU D0\n");
+ return ret_val;
+ }
+ /* Configure mdi-mdix settings */
+ ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
- if(hw->ffe_config_state == em_ffe_config_active)
- hw->ffe_config_state = em_ffe_config_enabled;
+ if ((hw->mac_type == em_82541) || (hw->mac_type == em_82547)) {
+ hw->dsp_config_state = em_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->dsp_config_state == em_dsp_config_activated)
- hw->dsp_config_state = em_dsp_config_enabled;
+ } else {
+ hw->dsp_config_state = em_dsp_config_enabled;
+ phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
- /* 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 = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- &phy_data);
- if(ret_val)
- return ret_val;
- phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = em_write_phy_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- phy_data);
- if(ret_val)
- return ret_val;
- /* Set auto Master/Slave resolution process */
- ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
- if(ret_val)
- return ret_val;
- phy_data &= ~CR_1000T_MS_ENABLE;
- ret_val = em_write_phy_reg(hw, PHY_1000T_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 = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
- ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
- if(ret_val)
- return ret_val;
+ /* set auto-master slave resolution settings */
+ if(hw->autoneg) {
+ em_ms_type phy_ms_setting = hw->master_slave;
- /* load defaults for future use */
- hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
- ((phy_data & CR_1000T_MS_VALUE) ?
- em_ms_force_master :
- em_ms_force_slave) :
- em_ms_auto;
-
- switch (phy_ms_setting) {
- case em_ms_force_master:
- phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
- break;
- case em_ms_force_slave:
- phy_data |= CR_1000T_MS_ENABLE;
- phy_data &= ~(CR_1000T_MS_VALUE);
- break;
- case em_ms_auto:
- phy_data &= ~CR_1000T_MS_ENABLE;
- default:
- break;
- }
- ret_val = em_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 = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
- &phy_data);
+ if(hw->ffe_config_state == em_ffe_config_active)
+ hw->ffe_config_state = em_ffe_config_enabled;
+
+ if(hw->dsp_config_state == em_dsp_config_activated)
+ hw->dsp_config_state = em_dsp_config_enabled;
+
+ /* 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 = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
if(ret_val)
return ret_val;
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = em_write_phy_reg(hw,
+ IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if(ret_val)
+ return ret_val;
+ /* Set auto Master/Slave resolution process */
+ ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
+ phy_data &= ~CR_1000T_MS_ENABLE;
+ ret_val = em_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
+ }
- phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+ ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
- /* 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;
+ /* load defaults for future use */
+ hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
+ ((phy_data & CR_1000T_MS_VALUE) ?
+ em_ms_force_master :
+ em_ms_force_slave) :
+ em_ms_auto;
- 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:
+ switch (phy_ms_setting) {
+ case em_ms_force_master:
+ phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
+ break;
+ case em_ms_force_slave:
+ phy_data |= CR_1000T_MS_ENABLE;
+ phy_data &= ~(CR_1000T_MS_VALUE);
+ break;
+ case em_ms_auto:
+ phy_data &= ~CR_1000T_MS_ENABLE;
default:
- phy_data |= M88E1000_PSCR_AUTO_X_MODE;
- break;
- }
+ break;
+ }
+ ret_val = em_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
+ }
- /* 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 = em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
- phy_data);
- if(ret_val)
- return ret_val;
+ return E1000_SUCCESS;
+}
- /* Force TX_CLK in the Extended PHY Specific Control Register
- * to 25MHz clock.
- */
- ret_val = em_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
- &phy_data);
- if(ret_val)
- return ret_val;
- phy_data |= M88E1000_EPSCR_TX_CLK_25;
+/********************************************************************
+* Copper link setup for em_phy_m88 series.
+*
+* hw - Struct containing variables accessed by shared code
+*********************************************************************/
+static int32_t
+em_copper_link_mgp_setup(struct em_hw *hw)
+{
+ int32_t ret_val;
+ uint16_t phy_data;
+
+ DEBUGFUNC("em_copper_link_mgp_setup");
+
+ if(hw->phy_reset_disable)
+ return E1000_SUCCESS;
+
+ /* Enable CRS on TX. This must be set for half-duplex operation. */
+ ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+
+ /* 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;
+
+ 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
+ */
+ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
+ if(hw->disable_polarity_correction == 1)
+ phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
+ ret_val = em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
+
+ /* Force TX_CLK in the Extended PHY Specific Control Register
+ * to 25MHz clock.
+ */
+ ret_val = em_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_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 |
+ 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 |
+ phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
- ret_val = em_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
- phy_data);
- if(ret_val)
- return ret_val;
- }
+ ret_val = em_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
+ }
- /* SW Reset the PHY so all changes take effect */
- ret_val = em_phy_reset(hw);
- if(ret_val) {
- DEBUGOUT("Error Resetting the PHY\n");
- return ret_val;
- }
+ /* SW Reset the PHY so all changes take effect */
+ ret_val = em_phy_reset(hw);
+ if(ret_val) {
+ DEBUGOUT("Error Resetting the PHY\n");
+ return ret_val;
+ }
+
+ return E1000_SUCCESS;
+}
+
+/********************************************************************
+* Setup auto-negotiation and flow control advertisements,
+* and then perform auto-negotiation.
+*
+* hw - Struct containing variables accessed by shared code
+*********************************************************************/
+static int32_t
+em_copper_link_autoneg(struct em_hw *hw)
+{
+ int32_t ret_val;
+ uint16_t phy_data;
+
+ DEBUGFUNC("em_copper_link_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;
+
+ DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
+ ret_val = em_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 = em_read_phy_reg(hw, PHY_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
+ ret_val = em_write_phy_reg(hw, PHY_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
+
+ /* 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 = em_wait_autoneg(hw);
+ if(ret_val) {
+ DEBUGOUT("Error while waiting for autoneg to complete\n");
+ 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.
- */
+ hw->get_link_status = TRUE;
- /* Is autoneg enabled? This is enabled by default or by software
- * override. If so, call em_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 em_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;
+ return E1000_SUCCESS;
+}
- /* 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 = em_phy_setup_autoneg(hw);
- if(ret_val) {
- DEBUGOUT("Error Setting up Auto-Negotiation\n");
- return ret_val;
- }
- DEBUGOUT("Restarting Auto-Neg\n");
+/******************************************************************************
+* 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
+em_copper_link_postconfig(struct em_hw *hw)
+{
+ int32_t ret_val;
+ DEBUGFUNC("em_copper_link_postconfig");
+
+ if(hw->mac_type >= em_82544) {
+ em_config_collision_dist(hw);
+ } else {
+ ret_val = em_config_mac_to_phy(hw);
+ if(ret_val) {
+ DEBUGOUT("Error configuring MAC to PHY settings\n");
+ return ret_val;
+ }
+ }
+ ret_val = em_config_fc_after_link_up(hw);
+ if(ret_val) {
+ DEBUGOUT("Error Configuring Flow Control\n");
+ return ret_val;
+ }
- /* Restart auto-negotiation by setting the Auto Neg Enable bit and
- * the Auto Neg Restart bit in the PHY control register.
- */
- ret_val = em_read_phy_reg(hw, PHY_CTRL, &phy_data);
- if(ret_val)
- return ret_val;
+ /* Config DSP to improve Giga link quality */
+ if(hw->phy_type == em_phy_igp) {
+ ret_val = em_config_dsp_after_link_change(hw, TRUE);
+ if(ret_val) {
+ DEBUGOUT("Error Configuring DSP after link up\n");
+ return ret_val;
+ }
+ }
+
+ return E1000_SUCCESS;
+}
- phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
- ret_val = em_write_phy_reg(hw, PHY_CTRL, phy_data);
- if(ret_val)
- return ret_val;
+/******************************************************************************
+* Detects which PHY is present and setup the speed and duplex
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+static int32_t
+em_setup_copper_link(struct em_hw *hw)
+{
+ int32_t ret_val;
+ uint16_t i;
+ uint16_t phy_data;
- /* 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 = em_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 = em_phy_force_speed_duplex(hw);
- if(ret_val) {
- DEBUGOUT("Error Forcing Speed and Duplex\n");
- return ret_val;
- }
+ DEBUGFUNC("em_setup_copper_link");
+
+ /* Check if it is a valid PHY and set PHY mode if necessary. */
+ ret_val = em_copper_link_preconfig(hw);
+ if(ret_val)
+ return ret_val;
+
+ if (hw->phy_type == em_phy_igp ||
+ hw->phy_type == em_phy_igp_2) {
+ ret_val = em_copper_link_igp_setup(hw);
+ if(ret_val)
+ return ret_val;
+ } else if (hw->phy_type == em_phy_m88) {
+ ret_val = em_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 = em_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 = em_phy_force_speed_duplex(hw);
+ if(ret_val) {
+ DEBUGOUT("Error Forcing Speed and Duplex\n");
+ return ret_val;
}
- } /* !hw->phy_reset_disable */
+ }
/* Check link status. Wait up to 100 microseconds for link to become
* valid.
@@ -1213,37 +1464,11 @@ em_setup_copper_link(struct em_hw *hw)
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 >= em_82544) {
- em_config_collision_dist(hw);
- } else {
- ret_val = em_config_mac_to_phy(hw);
- if(ret_val) {
- DEBUGOUT("Error configuring MAC to PHY settings\n");
- return ret_val;
- }
- }
- ret_val = em_config_fc_after_link_up(hw);
- if(ret_val) {
- DEBUGOUT("Error Configuring Flow Control\n");
+ /* Config the MAC and PHY after link is up */
+ ret_val = em_copper_link_postconfig(hw);
+ if(ret_val)
return ret_val;
- }
- DEBUGOUT("Valid link established!!!\n");
-
- if(hw->phy_type == em_phy_igp) {
- ret_val = em_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;
}
@@ -1273,10 +1498,10 @@ em_phy_setup_autoneg(struct em_hw *hw)
if(ret_val)
return ret_val;
- /* Read the MII 1000Base-T Control Register (Address 9). */
- ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
- if(ret_val)
- return ret_val;
+ /* Read the MII 1000Base-T Control Register (Address 9). */
+ ret_val = em_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
@@ -1388,7 +1613,7 @@ em_phy_setup_autoneg(struct em_hw *hw)
DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
- ret_val = em_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
+ ret_val = em_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
if(ret_val)
return ret_val;
@@ -1476,16 +1701,16 @@ em_phy_force_speed_duplex(struct em_hw *hw)
E1000_WRITE_REG(hw, CTRL, ctrl);
if (hw->phy_type == em_phy_m88) {
- if((ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
- &phy_data)))
+ ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ if(ret_val)
return ret_val;
/* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
* forced whenever speed are duplex are forced.
*/
phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
- if((ret_val = em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
- phy_data)))
+ ret_val = em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+ if(ret_val)
return ret_val;
DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data);
@@ -1496,20 +1721,21 @@ em_phy_force_speed_duplex(struct em_hw *hw)
/* Clear Auto-Crossover to force MDI manually. IGP requires MDI
* forced whenever speed or duplex are forced.
*/
- if((ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
- &phy_data)))
+ ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
+ if(ret_val)
return ret_val;
phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
- if((ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
- phy_data)))
+ ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
+ if(ret_val)
return ret_val;
}
/* Write back the modified PHY MII control register. */
- if((ret_val = em_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg)))
+ ret_val = em_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg);
+ if(ret_val)
return ret_val;
usec_delay(1);
@@ -1542,7 +1768,8 @@ em_phy_force_speed_duplex(struct em_hw *hw)
if(mii_status_reg & MII_SR_LINK_STATUS) break;
msec_delay(100);
}
- if((i == 0) && (hw->phy_type == em_phy_m88)) {
+ if((i == 0) &&
+ (hw->phy_type == em_phy_m88)) {
/* We didn't get link. Reset the DSP and wait again for link. */
ret_val = em_phy_reset_dsp(hw);
if(ret_val) {
@@ -1592,6 +1819,15 @@ em_phy_force_speed_duplex(struct em_hw *hw)
ret_val = em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
if(ret_val)
return ret_val;
+
+ if((hw->mac_type == em_82544 || hw->mac_type == em_82543) &&
+ (!hw->autoneg) &&
+ (hw->forced_speed_duplex == em_10_full ||
+ hw->forced_speed_duplex == em_10_half)) {
+ ret_val = em_polarity_reversal_workaround(hw);
+ if(ret_val)
+ return ret_val;
+ }
}
return E1000_SUCCESS;
}
@@ -1638,6 +1874,11 @@ em_config_mac_to_phy(struct em_hw *hw)
DEBUGFUNC("em_config_mac_to_phy");
+ /* 82544 or newer MAC, Auto Speed Detection takes care of
+ * MAC speed/duplex configuration.*/
+ if (hw->mac_type >= em_82544)
+ return E1000_SUCCESS;
+
/* Read the Device Control Register and set the bits to Force Speed
* and Duplex.
*/
@@ -1648,45 +1889,25 @@ em_config_mac_to_phy(struct em_hw *hw)
/* Set up duplex in the Device Control and Transmit Control
* registers depending on negotiated values.
*/
- if (hw->phy_type == em_phy_igp) {
- ret_val = em_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;
-
- em_config_collision_dist(hw);
+ ret_val = em_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 = em_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;
+ em_config_collision_dist(hw);
- em_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;
@@ -1981,6 +2202,7 @@ em_check_for_link(struct em_hw *hw)
uint32_t ctrl;
uint32_t status;
uint32_t rctl;
+ uint32_t icr;
uint32_t signal = 0;
int32_t ret_val;
uint16_t phy_data;
@@ -2030,6 +2252,25 @@ em_check_for_link(struct em_hw *hw)
* link-up */
em_check_downshift(hw);
+ /* If we are on 82544 or 82543 silicon and speed/duplex
+ * are forced to 10H or 10F, then we will implement the polarity
+ * reversal workaround. We disable interrupts first, and upon
+ * returning, place the devices interrupt state to its previous
+ * value except for the link status change interrupt which will
+ * happen due to the execution of this workaround.
+ */
+
+ if((hw->mac_type == em_82544 || hw->mac_type == em_82543) &&
+ (!hw->autoneg) &&
+ (hw->forced_speed_duplex == em_10_full ||
+ hw->forced_speed_duplex == em_10_half)) {
+ E1000_WRITE_REG(hw, IMC, 0xffffffff);
+ ret_val = em_polarity_reversal_workaround(hw);
+ icr = E1000_READ_REG(hw, ICR);
+ E1000_WRITE_REG(hw, ICS, (icr & ~E1000_ICS_LSC));
+ E1000_WRITE_REG(hw, IMS, IMS_ENABLE_MASK);
+ }
+
} else {
/* No link detected */
em_config_dsp_after_link_change(hw, FALSE);
@@ -2079,7 +2320,7 @@ em_check_for_link(struct em_hw *hw)
* at gigabit speed, then TBI compatibility is not needed. If we are
* at gigabit speed, we turn on TBI compatibility.
*/
- if(hw->tbi_compatibility_en) {
+ if(hw->tbi_compatibility_en) {
uint16_t speed, duplex;
em_get_speed_and_duplex(hw, &speed, &duplex);
if(speed != SPEED_1000) {
@@ -2434,15 +2675,17 @@ em_read_phy_reg(struct em_hw *hw,
DEBUGFUNC("em_read_phy_reg");
- if(hw->phy_type == em_phy_igp &&
+ if((hw->phy_type == em_phy_igp ||
+ hw->phy_type == em_phy_igp_2) &&
(reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
ret_val = em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
(uint16_t)reg_addr);
- if(ret_val)
+ if(ret_val) {
return ret_val;
+ }
}
- ret_val = em_read_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr,
+ ret_val = em_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
phy_data);
return ret_val;
@@ -2538,15 +2781,17 @@ em_write_phy_reg(struct em_hw *hw,
DEBUGFUNC("em_write_phy_reg");
- if(hw->phy_type == em_phy_igp &&
+ if((hw->phy_type == em_phy_igp ||
+ hw->phy_type == em_phy_igp_2) &&
(reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
ret_val = em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
(uint16_t)reg_addr);
- if(ret_val)
+ if(ret_val) {
return ret_val;
+ }
}
- ret_val = em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr,
+ ret_val = em_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
phy_data);
return ret_val;
@@ -2615,19 +2860,27 @@ em_write_phy_reg_ex(struct em_hw *hw,
return E1000_SUCCESS;
}
+
/******************************************************************************
* Returns the PHY to the power-on reset state
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-void
+int32_t
em_phy_hw_reset(struct em_hw *hw)
{
uint32_t ctrl, ctrl_ext;
uint32_t led_ctrl;
+ int32_t ret_val;
DEBUGFUNC("em_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 = em_check_phy_reset_block(hw);
+ if (ret_val)
+ return E1000_SUCCESS;
+
DEBUGOUT("Resetting Phy...\n");
if(hw->mac_type > em_82543) {
@@ -2663,6 +2916,11 @@ em_phy_hw_reset(struct em_hw *hw)
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 = em_get_phy_cfg_done(hw);
+
+ return ret_val;
}
/******************************************************************************
@@ -2680,7 +2938,19 @@ em_phy_reset(struct em_hw *hw)
DEBUGFUNC("em_phy_reset");
- if(hw->mac_type != em_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 = em_check_phy_reset_block(hw);
+ if (ret_val)
+ return E1000_SUCCESS;
+
+ switch (hw->mac_type) {
+ case em_82541_rev_2:
+ ret_val = em_phy_hw_reset(hw);
+ if(ret_val)
+ return ret_val;
+ break;
+ default:
ret_val = em_read_phy_reg(hw, PHY_CTRL, &phy_data);
if(ret_val)
return ret_val;
@@ -2691,9 +2961,10 @@ em_phy_reset(struct em_hw *hw)
return ret_val;
usec_delay(1);
- } else em_phy_hw_reset(hw);
+ break;
+ }
- if(hw->phy_type == em_phy_igp)
+ if(hw->phy_type == em_phy_igp || hw->phy_type == em_phy_igp_2)
em_phy_init_script(hw);
return E1000_SUCCESS;
@@ -2747,6 +3018,9 @@ em_detect_gig_phy(struct em_hw *hw)
case em_82547_rev_2:
if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
break;
+ case em_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;
@@ -2802,7 +3076,7 @@ em_phy_igp_get_info(struct em_hw *hw,
/* 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 = (em_downshift)hw->speed_downgraded;
/* IGP01E1000 does not need to support it. */
phy_info->extended_10bt_distance = em_10bt_ext_dist_enable_normal;
@@ -2841,7 +3115,7 @@ em_phy_igp_get_info(struct em_hw *hw,
if(ret_val)
return ret_val;
- /* transalte to old method */
+ /* Translate to old method */
average = (max_length + min_length) / 2;
if(average <= em_igp_cable_length_50)
@@ -2876,7 +3150,7 @@ em_phy_m88_get_info(struct em_hw *hw,
/* 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 = (em_downshift)hw->speed_downgraded;
ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if(ret_val)
@@ -2892,8 +3166,7 @@ em_phy_m88_get_info(struct em_hw *hw,
/* Check polarity status */
ret_val = em_check_polarity(hw, &polarity);
if(ret_val)
- return ret_val;
-
+ return ret_val;
phy_info->cable_polarity = polarity;
ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
@@ -2903,9 +3176,9 @@ em_phy_m88_get_info(struct em_hw *hw,
phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >>
M88E1000_PSSR_MDIX_SHIFT;
- if(phy_data & M88E1000_PSSR_1000MBS) {
- /* Cable Length Estimation and Local/Remote Receiver Informatoion
- * are only valid at 1000 Mbps
+ if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
+ /* Cable Length Estimation and Local/Remote Receiver Information
+ * are only valid at 1000 Mbps.
*/
phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
M88E1000_PSSR_CABLE_LENGTH_SHIFT);
@@ -2966,7 +3239,8 @@ em_phy_get_info(struct em_hw *hw,
return -E1000_ERR_CONFIG;
}
- if(hw->phy_type == em_phy_igp)
+ if(hw->phy_type == em_phy_igp ||
+ hw->phy_type == em_phy_igp_2)
return em_phy_igp_get_info(hw, phy_info);
else
return em_phy_m88_get_info(hw, phy_info);
@@ -2992,11 +3266,12 @@ em_validate_mdi_setting(struct em_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void
+int32_t
em_init_eeprom_params(struct em_hw *hw)
{
struct em_eeprom_info *eeprom = &hw->eeprom;
uint32_t eecd = E1000_READ_REG(hw, EECD);
+ int32_t ret_val = E1000_SUCCESS;
uint16_t eeprom_size;
DEBUGFUNC("em_init_eeprom_params");
@@ -3011,6 +3286,8 @@ em_init_eeprom_params(struct em_hw *hw)
eeprom->opcode_bits = 3;
eeprom->address_bits = 6;
eeprom->delay_usec = 50;
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
break;
case em_82540:
case em_82545:
@@ -3027,6 +3304,8 @@ em_init_eeprom_params(struct em_hw *hw)
eeprom->word_size = 64;
eeprom->address_bits = 6;
}
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
break;
case em_82541:
case em_82541_rev_2:
@@ -3055,8 +3334,10 @@ em_init_eeprom_params(struct em_hw *hw)
eeprom->address_bits = 6;
}
}
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
break;
- default:
+ case em_82573:
eeprom->type = em_eeprom_spi;
eeprom->opcode_bits = 8;
eeprom->delay_usec = 1;
@@ -3067,40 +3348,46 @@ em_init_eeprom_params(struct em_hw *hw)
eeprom->page_size = 8;
eeprom->address_bits = 8;
}
+ eeprom->use_eerd = TRUE;
+ eeprom->use_eewr = TRUE;
+ if(em_is_onboard_nvm_eeprom(hw) == FALSE) {
+ eeprom->type = em_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 == em_eeprom_spi) {
- eeprom->word_size = 64;
- if (em_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 <= em_82547_rev_2) {
+ /* Set to default value for initial eeprom read. */
+ eeprom->word_size = 64;
+ ret_val = em_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;
}
/******************************************************************************
@@ -3253,8 +3540,12 @@ em_acquire_eeprom(struct em_hw *hw)
DEBUGFUNC("em_acquire_eeprom");
+ if(em_get_hw_eeprom_semaphore(hw))
+ return -E1000_ERR_EEPROM;
+
eecd = E1000_READ_REG(hw, EECD);
+ if (hw->mac_type != em_82573) {
/* Request EEPROM Access */
if(hw->mac_type > em_82544) {
eecd |= E1000_EECD_REQ;
@@ -3273,6 +3564,7 @@ em_acquire_eeprom(struct em_hw *hw)
return -E1000_ERR_EEPROM;
}
}
+ }
/* Setup EEPROM for Read/Write */
@@ -3390,6 +3682,8 @@ em_release_eeprom(struct em_hw *hw)
eecd &= ~E1000_EECD_REQ;
E1000_WRITE_REG(hw, EECD, eecd);
}
+
+ em_put_hw_eeprom_semaphore(hw);
}
/******************************************************************************
@@ -3451,21 +3745,36 @@ em_read_eeprom(struct em_hw *hw,
{
struct em_eeprom_info *eeprom = &hw->eeprom;
uint32_t i = 0;
+ int32_t ret_val;
DEBUGFUNC("em_read_eeprom");
/* A check for invalid values: offset too large, too many words, and not
* enough words.
*/
- if((offset > eeprom->word_size) || (words > eeprom->word_size - offset) ||
+ if((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) ||
(words == 0)) {
DEBUGOUT("\"words\" parameter out of bounds\n");
return -E1000_ERR_EEPROM;
}
- /* Prepare the EEPROM for reading */
- if(em_acquire_eeprom(hw) != E1000_SUCCESS)
- return -E1000_ERR_EEPROM;
+ /* FLASH reads without acquiring the semaphore are safe in 82573-based
+ * controllers.
+ */
+ if ((em_is_onboard_nvm_eeprom(hw) == TRUE) ||
+ (hw->mac_type != em_82573)) {
+ /* Prepare the EEPROM for reading */
+ if(em_acquire_eeprom(hw) != E1000_SUCCESS)
+ return -E1000_ERR_EEPROM;
+ }
+
+ if(eeprom->use_eerd == TRUE) {
+ ret_val = em_read_eeprom_eerd(hw, offset, words, data);
+ if ((em_is_onboard_nvm_eeprom(hw) == TRUE) ||
+ (hw->mac_type != em_82573))
+ em_release_eeprom(hw);
+ return ret_val;
+ }
if(eeprom->type == em_eeprom_spi) {
uint16_t word_in;
@@ -3517,6 +3826,132 @@ em_read_eeprom(struct em_hw *hw,
}
/******************************************************************************
+ * Reads a 16 bit word from the EEPROM using the EERD register.
+ *
+ * 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
+em_read_eeprom_eerd(struct em_hw *hw,
+ uint16_t offset,
+ uint16_t words,
+ uint16_t *data)
+{
+ uint32_t i, eerd = 0;
+ int32_t error = 0;
+
+ for (i = 0; i < words; i++) {
+ eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) +
+ E1000_EEPROM_RW_REG_START;
+
+ E1000_WRITE_REG(hw, EERD, eerd);
+ error = em_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ);
+
+ if(error) {
+ break;
+ }
+ data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA);
+
+ }
+
+ return error;
+}
+
+/******************************************************************************
+ * Writes a 16 bit word from the EEPROM using the EEWR register.
+ *
+ * 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
+em_write_eeprom_eewr(struct em_hw *hw,
+ uint16_t offset,
+ uint16_t words,
+ uint16_t *data)
+{
+ uint32_t register_value = 0;
+ uint32_t i = 0;
+ int32_t error = 0;
+
+ 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;
+
+ error = em_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
+ if(error) {
+ break;
+ }
+
+ E1000_WRITE_REG(hw, EEWR, register_value);
+
+ error = em_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
+em_poll_eerd_eewr_done(struct em_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;
+ }
+ usec_delay(5);
+ }
+
+ return done;
+}
+
+/***************************************************************************
+* Description: Determines if the onboard NVM is FLASH or EEPROM.
+*
+* hw - Struct containing variables accessed by shared code
+****************************************************************************/
+boolean_t
+em_is_onboard_nvm_eeprom(struct em_hw *hw)
+{
+ uint32_t eecd = 0;
+
+ if(hw->mac_type == em_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
@@ -3533,6 +3968,25 @@ em_validate_eeprom_checksum(struct em_hw *hw)
DEBUGFUNC("em_validate_eeprom_checksum");
+ if ((hw->mac_type == em_82573) &&
+ (em_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. */
+ em_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. */
+ em_read_eeprom(hw, 0x23, 1, &eeprom_data);
+ if ((eeprom_data & 0x8000) == 0) {
+ eeprom_data |= 0x8000;
+ em_write_eeprom(hw, 0x23, 1, &eeprom_data);
+ em_update_eeprom_checksum(hw);
+ }
+ }
+ }
+
for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
if(em_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n");
@@ -3576,6 +4030,8 @@ em_update_eeprom_checksum(struct em_hw *hw)
if(em_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
DEBUGOUT("EEPROM Write Error\n");
return -E1000_ERR_EEPROM;
+ } else if (hw->eeprom.type == em_eeprom_flash) {
+ em_commit_shadow_ram(hw);
}
return E1000_SUCCESS;
}
@@ -3605,12 +4061,16 @@ em_write_eeprom(struct em_hw *hw,
/* A check for invalid values: offset too large, too many words, and not
* enough words.
*/
- if((offset > eeprom->word_size) || (words > eeprom->word_size - offset) ||
+ if((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) ||
(words == 0)) {
DEBUGOUT("\"words\" parameter out of bounds\n");
return -E1000_ERR_EEPROM;
}
+ /* 82573 reads only through eerd */
+ if(eeprom->use_eewr == TRUE)
+ return em_write_eeprom_eewr(hw, offset, words, data);
+
/* Prepare the EEPROM for writing */
if (em_acquire_eeprom(hw) != E1000_SUCCESS)
return -E1000_ERR_EEPROM;
@@ -3781,6 +4241,65 @@ em_write_eeprom_microwire(struct em_hw *hw,
}
/******************************************************************************
+ * 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
+em_commit_shadow_ram(struct em_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 == em_82573) {
+ for (i=0; i < attempts; i++) {
+ eecd = E1000_READ_REG(hw, EECD);
+ if ((eecd & E1000_EECD_FLUPD) == 0) {
+ break;
+ }
+ usec_delay(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;
+ }
+ usec_delay(5);
+ }
+
+ if (i == attempts) {
+ return -E1000_ERR_EEPROM;
+ }
+ }
+
+ return error;
+}
+
+/******************************************************************************
* Reads the adapter's part number from the EEPROM
*
* hw - Struct containing variables accessed by shared code
@@ -3859,6 +4378,7 @@ void
em_init_rx_addrs(struct em_hw *hw)
{
uint32_t i;
+ uint32_t rar_num;
DEBUGFUNC("em_init_rx_addrs");
@@ -3867,9 +4387,10 @@ em_init_rx_addrs(struct em_hw *hw)
em_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);
}
@@ -3898,7 +4419,9 @@ em_mc_addr_list_update(struct em_hw *hw,
{
uint32_t hash_value;
uint32_t i;
-
+ uint32_t num_rar_entry;
+ uint32_t num_mta_entry;
+
DEBUGFUNC("em_mc_addr_list_update");
/* Set the new number of MC addresses that we are being requested to use. */
@@ -3906,14 +4429,16 @@ em_mc_addr_list_update(struct em_hw *hw,
/* 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);
}
@@ -3937,7 +4462,7 @@ em_mc_addr_list_update(struct em_hw *hw,
/* 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) {
em_rar_set(hw,
mc_addr_list + (i * (ETH_LENGTH_OF_ADDRESS + pad)),
rar_used_count);
@@ -3988,6 +4513,7 @@ em_hash_mc_addr(struct em_hw *hw,
}
hash_value &= 0xFFF;
+
return hash_value;
}
@@ -4092,12 +4618,33 @@ void
em_clear_vfta(struct em_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 == em_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
em_id_led_init(struct em_hw * hw)
{
uint32_t ledctl;
@@ -4428,6 +4975,19 @@ em_clear_hw_cntrs(struct em_hw *hw)
temp = E1000_READ_REG(hw, MGTPRC);
temp = E1000_READ_REG(hw, MGTPDC);
temp = E1000_READ_REG(hw, MGTPTC);
+
+ if(hw->mac_type <= em_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);
+
}
/******************************************************************************
@@ -4587,41 +5147,49 @@ em_get_bus_info(struct em_hw *hw)
{
uint32_t status;
- if(hw->mac_type < em_82543) {
+ switch (hw->mac_type) {
+ case em_82542_rev2_0:
+ case em_82542_rev2_1:
hw->bus_type = em_bus_type_unknown;
hw->bus_speed = em_bus_speed_unknown;
hw->bus_width = em_bus_width_unknown;
- return;
- }
-
- status = E1000_READ_REG(hw, STATUS);
- hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
- em_bus_type_pcix : em_bus_type_pci;
-
- if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
- hw->bus_speed = (hw->bus_type == em_bus_type_pci) ?
- em_bus_speed_66 : em_bus_speed_120;
- } else if(hw->bus_type == em_bus_type_pci) {
- hw->bus_speed = (status & E1000_STATUS_PCI66) ?
- em_bus_speed_66 : em_bus_speed_33;
- } else {
- switch (status & E1000_STATUS_PCIX_SPEED) {
- case E1000_STATUS_PCIX_SPEED_66:
- hw->bus_speed = em_bus_speed_66;
- break;
- case E1000_STATUS_PCIX_SPEED_100:
- hw->bus_speed = em_bus_speed_100;
- break;
- case E1000_STATUS_PCIX_SPEED_133:
- hw->bus_speed = em_bus_speed_133;
- break;
- default:
- hw->bus_speed = em_bus_speed_reserved;
- break;
+ break;
+ case em_82573:
+ hw->bus_type = em_bus_type_pci_express;
+ hw->bus_speed = em_bus_speed_2500;
+ hw->bus_width = em_bus_width_pciex_4;
+ break;
+ default:
+ status = E1000_READ_REG(hw, STATUS);
+ hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
+ em_bus_type_pcix : em_bus_type_pci;
+
+ if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
+ hw->bus_speed = (hw->bus_type == em_bus_type_pci) ?
+ em_bus_speed_66 : em_bus_speed_120;
+ } else if(hw->bus_type == em_bus_type_pci) {
+ hw->bus_speed = (status & E1000_STATUS_PCI66) ?
+ em_bus_speed_66 : em_bus_speed_33;
+ } else {
+ switch (status & E1000_STATUS_PCIX_SPEED) {
+ case E1000_STATUS_PCIX_SPEED_66:
+ hw->bus_speed = em_bus_speed_66;
+ break;
+ case E1000_STATUS_PCIX_SPEED_100:
+ hw->bus_speed = em_bus_speed_100;
+ break;
+ case E1000_STATUS_PCIX_SPEED_133:
+ hw->bus_speed = em_bus_speed_133;
+ break;
+ default:
+ hw->bus_speed = em_bus_speed_reserved;
+ break;
+ }
}
+ hw->bus_width = (status & E1000_STATUS_BUS64) ?
+ em_bus_width_64 : em_bus_width_32;
+ break;
}
- hw->bus_width = (status & E1000_STATUS_BUS64) ?
- em_bus_width_64 : em_bus_width_32;
}
/******************************************************************************
* Reads a value from one of the devices registers using port I/O (as opposed
@@ -4686,6 +5254,7 @@ em_get_cable_length(struct em_hw *hw,
uint16_t agc_value = 0;
uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
uint16_t i, phy_data;
+ uint16_t cable_length;
DEBUGFUNC("em_get_cable_length");
@@ -4693,14 +5262,16 @@ em_get_cable_length(struct em_hw *hw,
/* Use old method for Phy older than IGP */
if(hw->phy_type == em_phy_m88) {
+
ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
&phy_data);
if(ret_val)
return ret_val;
+ cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+ M88E1000_PSSR_CABLE_LENGTH_SHIFT;
/* Convert the enum value to ranged values */
- switch((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
- M88E1000_PSSR_CABLE_LENGTH_SHIFT) {
+ switch (cable_length) {
case em_cable_length_50:
*min_length = 0;
*max_length = em_igp_cable_length_50;
@@ -4808,7 +5379,8 @@ em_check_polarity(struct em_hw *hw,
return ret_val;
*polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >>
M88E1000_PSSR_REV_POLARITY_SHIFT;
- } else if(hw->phy_type == em_phy_igp) {
+ } else if(hw->phy_type == em_phy_igp ||
+ hw->phy_type == em_phy_igp_2) {
/* Read the Status register to check the speed */
ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
&phy_data);
@@ -4860,15 +5432,15 @@ em_check_downshift(struct em_hw *hw)
DEBUGFUNC("em_check_downshift");
- if(hw->phy_type == em_phy_igp) {
+ if(hw->phy_type == em_phy_igp ||
+ hw->phy_type == em_phy_igp_2) {
ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
&phy_data);
if(ret_val)
return ret_val;
hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
- }
- else if(hw->phy_type == em_phy_m88) {
+ } else if(hw->phy_type == em_phy_m88) {
ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
&phy_data);
if(ret_val)
@@ -4877,6 +5449,7 @@ em_check_downshift(struct em_hw *hw)
hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
M88E1000_PSSR_DOWNSHIFT_SHIFT;
}
+
return E1000_SUCCESS;
}
@@ -4897,7 +5470,7 @@ em_config_dsp_after_link_change(struct em_hw *hw,
boolean_t link_up)
{
int32_t ret_val;
- uint16_t phy_data, speed, duplex, i;
+ uint16_t phy_data, phy_saved_data, speed, duplex, i;
uint16_t dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
{IGP01E1000_PHY_AGC_PARAM_A,
IGP01E1000_PHY_AGC_PARAM_B,
@@ -4978,6 +5551,21 @@ em_config_dsp_after_link_change(struct em_hw *hw,
}
} else {
if(hw->dsp_config_state == em_dsp_config_activated) {
+ /* Save off the current value of register 0x2F5B to be restored at
+ * the end of the routines. */
+ ret_val = em_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
+
+ if(ret_val)
+ return ret_val;
+
+ /* Disable the PHY transmitter */
+ ret_val = em_write_phy_reg(hw, 0x2F5B, 0x0003);
+
+ if(ret_val)
+ return ret_val;
+
+ msec_delay_irq(20);
+
ret_val = em_write_phy_reg(hw, 0x0000,
IGP01E1000_IEEE_FORCE_GIGA);
if(ret_val)
@@ -5000,10 +5588,33 @@ em_config_dsp_after_link_change(struct em_hw *hw,
if(ret_val)
return ret_val;
+ msec_delay_irq(20);
+
+ /* Now enable the transmitter */
+ ret_val = em_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+
+ if(ret_val)
+ return ret_val;
+
hw->dsp_config_state = em_dsp_config_enabled;
}
if(hw->ffe_config_state == em_ffe_config_active) {
+ /* Save off the current value of register 0x2F5B to be restored at
+ * the end of the routines. */
+ ret_val = em_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
+
+ if(ret_val)
+ return ret_val;
+
+ /* Disable the PHY transmitter */
+ ret_val = em_write_phy_reg(hw, 0x2F5B, 0x0003);
+
+ if(ret_val)
+ return ret_val;
+
+ msec_delay_irq(20);
+
ret_val = em_write_phy_reg(hw, 0x0000,
IGP01E1000_IEEE_FORCE_GIGA);
if(ret_val)
@@ -5017,6 +5628,15 @@ em_config_dsp_after_link_change(struct em_hw *hw,
IGP01E1000_IEEE_RESTART_AUTONEG);
if(ret_val)
return ret_val;
+
+ msec_delay_irq(20);
+
+ /* Now enable the transmitter */
+ ret_val = em_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+
+ if(ret_val)
+ return ret_val;
+
hw->ffe_config_state = em_ffe_config_enabled;
}
}
@@ -5084,45 +5704,168 @@ em_set_d3_lplu_state(struct em_hw *hw,
uint16_t phy_data;
DEBUGFUNC("em_set_d3_lplu_state");
- if(!((hw->mac_type == em_82541_rev_2) ||
- (hw->mac_type == em_82547_rev_2)))
+ if(hw->phy_type != em_phy_igp && hw->phy_type != em_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 = em_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 = em_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+ if(hw->mac_type == em_82541_rev_2 || hw->mac_type == em_82547_rev_2) {
+ ret_val = em_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
+ if(ret_val)
+ return ret_val;
+ } else {
+ ret_val = em_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
if(ret_val)
return ret_val;
+ }
+
+ if(!active) {
+ if(hw->mac_type == em_82541_rev_2 ||
+ hw->mac_type == em_82547_rev_2) {
+ phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
+ ret_val = em_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+ if(ret_val)
+ return ret_val;
+ } else {
+ phy_data &= ~IGP02E1000_PM_D3_LPLU;
+ ret_val = em_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 == em_smart_speed_on) {
+ ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if(ret_val)
+ return ret_val;
+ } else if (hw->smart_speed == em_smart_speed_off) {
+ ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if(ret_val)
+ return ret_val;
+ }
+
+ } else if((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) ||
+ (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) ||
+ (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) {
+
+ if(hw->mac_type == em_82541_rev_2 ||
+ hw->mac_type == em_82547_rev_2) {
+ phy_data |= IGP01E1000_GMII_FLEX_SPD;
+ ret_val = em_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+ if(ret_val)
+ return ret_val;
+ } else {
+ phy_data |= IGP02E1000_PM_D3_LPLU;
+ ret_val = em_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 = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
if(ret_val)
return ret_val;
- phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data);
if(ret_val)
return ret_val;
- } else if((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) ||
- (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) ||
- (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) {
+ }
+ 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.
+ *
+ ****************************************************************************/
- phy_data |= IGP01E1000_GMII_FLEX_SPD;
- ret_val = em_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+int32_t
+em_set_d0_lplu_state(struct em_hw *hw,
+ boolean_t active)
+{
+ int32_t ret_val;
+ uint16_t phy_data;
+ DEBUGFUNC("em_set_d0_lplu_state");
+
+ if(hw->mac_type <= em_82547_rev_2)
+ return E1000_SUCCESS;
+
+ ret_val = em_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 = em_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 == em_smart_speed_on) {
+ ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if(ret_val)
+ return ret_val;
+ } else if (hw->smart_speed == em_smart_speed_off) {
+ ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = em_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 = em_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 = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
if(ret_val)
@@ -5200,3 +5943,682 @@ em_set_vco_speed(struct em_hw *hw)
return E1000_SUCCESS;
}
+
+/*****************************************************************************
+ * This function reads the cookie from ARC ram.
+ *
+ * returns: - E1000_SUCCESS .
+ ****************************************************************************/
+int32_t
+em_host_if_read_cookie(struct em_hw * hw, uint8_t *buffer)
+{
+ uint8_t i;
+ uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET;
+ uint8_t length = E1000_MNG_DHCP_COOKIE_LENGTH;
+
+ length = (length >> 2);
+ offset = (offset >> 2);
+
+ 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
+em_mng_enable_host_if(struct em_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
+em_mng_host_if_write(struct em_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
+em_mng_write_cmd_header(struct em_hw * hw,
+ struct em_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 em_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
+em_mng_write_commit(
+ struct em_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
+em_check_mng_mode(
+ struct em_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
+em_mng_write_dhcp_info(struct em_hw * hw, uint8_t *buffer,
+ uint16_t length)
+{
+ int32_t ret_val;
+ struct em_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 = em_mng_enable_host_if(hw);
+ if (ret_val == E1000_SUCCESS) {
+ ret_val = em_mng_host_if_write(hw, buffer, length, sizeof(hdr),
+ &(hdr.checksum));
+ if (ret_val == E1000_SUCCESS) {
+ ret_val = em_mng_write_cmd_header(hw, &hdr);
+ if (ret_val == E1000_SUCCESS)
+ ret_val = em_mng_write_commit(hw);
+ }
+ }
+ return ret_val;
+}
+
+
+/*****************************************************************************
+ * This function calculates the checksum.
+ *
+ * returns - checksum of buffer contents.
+ ****************************************************************************/
+uint8_t
+em_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
+em_enable_tx_pkt_filtering(struct em_hw *hw)
+{
+ /* called in init as well as watchdog timer functions */
+
+ int32_t ret_val, checksum;
+ boolean_t tx_filter = FALSE;
+ struct em_host_mng_dhcp_cookie *hdr = &(hw->mng_cookie);
+ uint8_t *buffer = (uint8_t *) &(hw->mng_cookie);
+
+ if (em_check_mng_mode(hw)) {
+ ret_val = em_mng_enable_host_if(hw);
+ if (ret_val == E1000_SUCCESS) {
+ ret_val = em_host_if_read_cookie(hw, buffer);
+ if (ret_val == E1000_SUCCESS) {
+ checksum = hdr->checksum;
+ hdr->checksum = 0;
+ if ((hdr->signature == E1000_IAMT_SIGNATURE) &&
+ checksum == em_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
+em_enable_mng_pass_thru(struct em_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 (em_arc_subsystem_valid(hw) == TRUE) {
+ fwsm = E1000_READ_REG(hw, FWSM);
+ factps = E1000_READ_REG(hw, FACTPS);
+
+ if (((fwsm & E1000_FWSM_MODE_MASK) ==
+ (em_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
+em_polarity_reversal_workaround(struct em_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 = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+ if(ret_val)
+ return ret_val;
+ ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
+ if(ret_val)
+ return ret_val;
+
+ ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
+ if(ret_val)
+ return ret_val;
+
+ /* This loop will early-out if the NO link condition has been met. */
+ for(i = PHY_FORCE_TIME; i > 0; i--) {
+ /* Read the MII Status Register and wait for Link Status bit
+ * to be clear.
+ */
+
+ ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if(ret_val)
+ return ret_val;
+
+ ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if(ret_val)
+ return ret_val;
+
+ if((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) break;
+ msec_delay_irq(100);
+ }
+
+ /* Recommended delay time after link has been lost */
+ msec_delay_irq(1000);
+
+ /* Now we will re-enable th transmitter on the PHY */
+
+ ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+ if(ret_val)
+ return ret_val;
+ msec_delay_irq(50);
+ ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
+ if(ret_val)
+ return ret_val;
+ msec_delay_irq(50);
+ ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
+ if(ret_val)
+ return ret_val;
+ msec_delay_irq(50);
+ ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
+ if(ret_val)
+ return ret_val;
+
+ ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
+ if(ret_val)
+ return ret_val;
+
+ /* This loop will early-out if the link condition has been met. */
+ for(i = PHY_FORCE_TIME; i > 0; i--) {
+ /* Read the MII Status Register and wait for Link Status bit
+ * to be set.
+ */
+
+ ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if(ret_val)
+ return ret_val;
+
+ ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if(ret_val)
+ return ret_val;
+
+ if(mii_status_reg & MII_SR_LINK_STATUS) break;
+ msec_delay_irq(100);
+ }
+ return E1000_SUCCESS;
+}
+
+/***************************************************************************
+ *
+ * Disables PCI-Express master access.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - none.
+ *
+ ***************************************************************************/
+void
+em_set_pci_express_master_disable(struct em_hw *hw)
+{
+ uint32_t ctrl;
+
+ DEBUGFUNC("em_set_pci_express_master_disable");
+
+ if (hw->bus_type != em_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
+em_enable_pciex_master(struct em_hw *hw)
+{
+ uint32_t ctrl;
+
+ DEBUGFUNC("em_enable_pciex_master");
+
+ if (hw->bus_type != em_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
+em_disable_pciex_master(struct em_hw *hw)
+{
+ int32_t timeout = MASTER_DISABLE_TIMEOUT; /* 80ms */
+
+ DEBUGFUNC("em_disable_pciex_master");
+
+ if (hw->bus_type != em_bus_type_pci_express)
+ return E1000_SUCCESS;
+
+ em_set_pci_express_master_disable(hw);
+
+ while(timeout) {
+ if(!(E1000_READ_REG(hw, STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
+ break;
+ else
+ usec_delay(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
+em_get_auto_rd_done(struct em_hw *hw)
+{
+ int32_t timeout = AUTO_READ_DONE_TIMEOUT;
+
+ DEBUGFUNC("em_get_auto_rd_done");
+
+ switch (hw->mac_type) {
+ default:
+ msec_delay(5);
+ break;
+ case em_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
+em_get_phy_cfg_done(struct em_hw *hw)
+{
+ DEBUGFUNC("em_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
+em_get_hw_eeprom_semaphore(struct em_hw *hw)
+{
+ int32_t timeout;
+ uint32_t swsm;
+
+ DEBUGFUNC("em_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;
+
+ usec_delay(50);
+ timeout--;
+ }
+
+ if(!timeout) {
+ /* Release semaphores */
+ em_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
+em_put_hw_eeprom_semaphore(struct em_hw *hw)
+{
+ uint32_t swsm;
+
+ DEBUGFUNC("em_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
+em_check_phy_reset_block(struct em_hw *hw)
+{
+ uint32_t manc = 0;
+ if(hw->mac_type > em_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
+em_arc_subsystem_valid(struct em_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 em_82573:
+ fwsm = E1000_READ_REG(hw, FWSM);
+ if((fwsm & E1000_FWSM_MODE_MASK) != 0)
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+
+
diff --git a/sys/dev/em/if_em_hw.h b/sys/dev/em/if_em_hw.h
index f3574bd..5ad3853 100644
--- a/sys/dev/em/if_em_hw.h
+++ b/sys/dev/em/if_em_hw.h
@@ -1,6 +1,6 @@
/*******************************************************************************
- Copyright (c) 2001-2003, Intel Corporation
+ Copyright (c) 2001-2005, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -41,9 +41,6 @@
#include <dev/em/if_em_osdep.h>
-#ifndef NO_VERSION_CONTROL
-#ident "@(#)$RCSfile: if_em_hw.h,v $$Revision: 1.41 $$Date: 2004/05/17 15:18:53 $"
-#endif
/* Forward declarations of structures used by the shared code */
struct em_hw;
@@ -66,6 +63,7 @@ typedef enum {
em_82541_rev_2,
em_82547,
em_82547_rev_2,
+ em_82573,
em_num_macs
} em_mac_type;
@@ -73,6 +71,7 @@ typedef enum {
em_eeprom_uninitialized = 0,
em_eeprom_spi,
em_eeprom_microwire,
+ em_eeprom_flash,
em_num_eeprom_types
} em_eeprom_type;
@@ -105,6 +104,7 @@ typedef enum {
em_bus_type_unknown = 0,
em_bus_type_pci,
em_bus_type_pcix,
+ em_bus_type_pci_express,
em_bus_type_reserved
} em_bus_type;
@@ -116,6 +116,7 @@ typedef enum {
em_bus_speed_100,
em_bus_speed_120,
em_bus_speed_133,
+ em_bus_speed_2500,
em_bus_speed_reserved
} em_bus_speed;
@@ -124,6 +125,8 @@ typedef enum {
em_bus_width_unknown = 0,
em_bus_width_32,
em_bus_width_64,
+ em_bus_width_pciex_1,
+ em_bus_width_pciex_4,
em_bus_width_reserved
} em_bus_width;
@@ -177,6 +180,12 @@ typedef enum {
} em_downshift;
typedef enum {
+ em_smart_speed_default = 0,
+ em_smart_speed_on,
+ em_smart_speed_off
+} em_smart_speed;
+
+typedef enum {
em_polarity_reversal_enabled = 0,
em_polarity_reversal_disabled,
em_polarity_reversal_undefined = 0xFF
@@ -199,6 +208,7 @@ typedef enum {
typedef enum {
em_phy_m88 = 0,
em_phy_igp,
+ em_phy_igp_2,
em_phy_undefined = 0xFF
} em_phy_type;
@@ -245,8 +255,19 @@ struct em_eeprom_info {
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 {
+ em_byte_align = 0,
+ em_word_align = 1,
+ em_dword_align = 2
+} em_align_type;
+
/* Error Codes */
@@ -257,11 +278,16 @@ struct em_eeprom_info {
#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 em_reset_hw(struct em_hw *hw);
int32_t em_init_hw(struct em_hw *hw);
+int32_t em_id_led_init(struct em_hw * hw);
int32_t em_set_mac_type(struct em_hw *hw);
void em_set_media_type(struct em_hw *hw);
@@ -278,7 +304,7 @@ int32_t em_force_mac_fc(struct em_hw *hw);
/* PHY */
int32_t em_read_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t *phy_data);
int32_t em_write_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t data);
-void em_phy_hw_reset(struct em_hw *hw);
+int32_t em_phy_hw_reset(struct em_hw *hw);
int32_t em_phy_reset(struct em_hw *hw);
int32_t em_detect_gig_phy(struct em_hw *hw);
int32_t em_phy_get_info(struct em_hw *hw, struct em_phy_info *phy_info);
@@ -290,13 +316,86 @@ int32_t em_check_downshift(struct em_hw *hw);
int32_t em_validate_mdi_setting(struct em_hw *hw);
/* EEPROM Functions */
-void em_init_eeprom_params(struct em_hw *hw);
+int32_t em_init_eeprom_params(struct em_hw *hw);
+boolean_t em_is_onboard_nvm_eeprom(struct em_hw *hw);
+int32_t em_read_eeprom_eerd(struct em_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+int32_t em_write_eeprom_eewr(struct em_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+int32_t em_poll_eerd_eewr_done(struct em_hw *hw, int eerd);
+
+/* MNG HOST IF functions */
+uint32_t em_enable_mng_pass_thru(struct em_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 em_host_mng_command_header {
+ uint8_t command_id;
+ uint8_t checksum;
+ uint16_t reserved1;
+ uint16_t reserved2;
+ uint16_t command_length;
+};
+
+struct em_host_mng_command_info {
+ struct em_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 em_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 em_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 em_mng_write_dhcp_info(struct em_hw *hw, uint8_t *buffer,
+ uint16_t length);
+boolean_t em_check_mng_mode(struct em_hw *hw);
+boolean_t em_enable_tx_pkt_filtering(struct em_hw *hw);
+int32_t em_mng_enable_host_if(struct em_hw *hw);
+int32_t em_mng_host_if_write(struct em_hw *hw, uint8_t *buffer,
+ uint16_t length, uint16_t offset, uint8_t *sum);
+int32_t em_mng_write_cmd_header(struct em_hw* hw,
+ struct em_host_mng_command_header* hdr);
+
+int32_t em_mng_write_commit(struct em_hw *hw);
+
int32_t em_read_eeprom(struct em_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
int32_t em_validate_eeprom_checksum(struct em_hw *hw);
int32_t em_update_eeprom_checksum(struct em_hw *hw);
int32_t em_write_eeprom(struct em_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
int32_t em_read_part_num(struct em_hw *hw, uint32_t * part_num);
int32_t em_read_mac_addr(struct em_hw * hw);
+int32_t em_swfw_sync_acquire(struct em_hw *hw, uint16_t mask);
+void em_swfw_sync_release(struct em_hw *hw, uint16_t mask);
/* Filters (multicast, vlan, receive) */
void em_init_rx_addrs(struct em_hw *hw);
@@ -332,6 +431,19 @@ void em_io_write(struct em_hw *hw, unsigned long port, uint32_t value);
void em_write_reg_io(struct em_hw *hw, uint32_t offset, uint32_t value);
int32_t em_config_dsp_after_link_change(struct em_hw *hw, boolean_t link_up);
int32_t em_set_d3_lplu_state(struct em_hw *hw, boolean_t active);
+int32_t em_set_d0_lplu_state(struct em_hw *hw, boolean_t active);
+void em_set_pci_express_master_disable(struct em_hw *hw);
+void em_enable_pciex_master(struct em_hw *hw);
+int32_t em_disable_pciex_master(struct em_hw *hw);
+int32_t em_get_auto_rd_done(struct em_hw *hw);
+int32_t em_get_phy_cfg_done(struct em_hw *hw);
+int32_t em_get_software_semaphore(struct em_hw *hw);
+void em_release_software_semaphore(struct em_hw *hw);
+int32_t em_check_phy_reset_block(struct em_hw *hw);
+int32_t em_get_hw_eeprom_semaphore(struct em_hw *hw);
+void em_put_hw_eeprom_semaphore(struct em_hw *hw);
+int32_t em_commit_shadow_ram(struct em_hw *hw);
+uint8_t em_arc_subsystem_valid(struct em_hw *hw);
#define E1000_READ_REG_IO(a, reg) \
em_read_reg_io((a), E1000_##reg)
@@ -347,6 +459,7 @@ int32_t em_set_d3_lplu_state(struct em_hw *hw, boolean_t active);
#define E1000_DEV_ID_82544GC_COPPER 0x100C
#define E1000_DEV_ID_82544GC_LOM 0x100D
#define E1000_DEV_ID_82540EM 0x100E
+#define E1000_DEV_ID_82541ER_LOM 0x1014
#define E1000_DEV_ID_82540EM_LOM 0x1015
#define E1000_DEV_ID_82540EP_LOM 0x1016
#define E1000_DEV_ID_82540EP 0x1017
@@ -369,7 +482,13 @@ int32_t em_set_d3_lplu_state(struct em_hw *hw, boolean_t active);
#define E1000_DEV_ID_82546GB_COPPER 0x1079
#define E1000_DEV_ID_82546GB_FIBER 0x107A
#define E1000_DEV_ID_82546GB_SERDES 0x107B
+#define E1000_DEV_ID_82546GB_PCIE 0x108A
#define E1000_DEV_ID_82547EI 0x1019
+#define E1000_DEV_ID_82547EI_MOBILE 0x101A
+#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
@@ -382,6 +501,7 @@ int32_t em_set_d3_lplu_state(struct em_hw *hw, boolean_t active);
#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
@@ -438,6 +558,7 @@ int32_t em_set_d3_lplu_state(struct em_hw *hw, boolean_t active);
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
@@ -458,14 +579,74 @@ struct em_rx_desc {
uint16_t special;
};
+/* Receive Descriptor - Extended */
+union em_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 em_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 */
@@ -475,9 +656,20 @@ struct em_rx_desc {
#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 ( \
@@ -487,6 +679,15 @@ struct em_rx_desc {
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 em_tx_desc {
uint64_t buffer_addr; /* Address of the descriptor's data buffer */
@@ -668,6 +869,7 @@ struct em_ffvt_entry {
#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 */
@@ -677,9 +879,23 @@ struct em_ffvt_entry {
#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 */
@@ -689,6 +905,7 @@ struct em_ffvt_entry {
#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 */
@@ -704,6 +921,14 @@ struct em_ffvt_entry {
#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 */
@@ -762,7 +987,17 @@ struct em_ffvt_entry {
#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 */
@@ -780,6 +1015,16 @@ struct em_ffvt_entry {
#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
@@ -830,6 +1075,18 @@ struct em_ffvt_entry {
#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
@@ -914,6 +1171,38 @@ struct em_ffvt_entry {
#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 em_hw_stats {
@@ -975,11 +1264,21 @@ struct em_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 (em_hw.c) */
struct em_hw {
uint8_t *hw_addr;
+ uint8_t *flash_address;
em_mac_type mac_type;
em_phy_type phy_type;
uint32_t phy_init_script;
@@ -993,6 +1292,8 @@ struct em_hw {
em_ms_type master_slave;
em_ms_type original_master_slave;
em_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;
@@ -1009,6 +1310,8 @@ struct em_hw {
uint32_t ledctl_default;
uint32_t ledctl_mode1;
uint32_t ledctl_mode2;
+ boolean_t tx_pkt_filtering;
+ struct em_host_mng_dhcp_cookie mng_cookie;
uint16_t phy_spd_default;
uint16_t autoneg_advertised;
uint16_t pci_cmd_word;
@@ -1034,6 +1337,7 @@ struct em_hw {
uint8_t perm_mac_addr[NODE_ADDRESS_SIZE];
boolean_t disable_polarity_correction;
boolean_t speed_downgraded;
+ em_smart_speed smart_speed;
em_dsp_config dsp_config_state;
boolean_t get_link_status;
boolean_t serdes_link_down;
@@ -1046,17 +1350,24 @@ struct em_hw {
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 */
@@ -1070,6 +1381,7 @@ struct em_hw {
#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 */
@@ -1089,6 +1401,7 @@ struct em_hw {
#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 */
@@ -1098,6 +1411,8 @@ struct em_hw {
#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 */
@@ -1128,6 +1443,18 @@ struct em_hw {
#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 */
@@ -1171,6 +1498,8 @@ struct em_hw {
#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
@@ -1187,14 +1516,17 @@ struct em_hw {
/* 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
@@ -1238,6 +1570,10 @@ struct em_hw {
#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 */
@@ -1255,6 +1591,9 @@ struct em_hw {
#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 */
@@ -1272,6 +1611,9 @@ struct em_hw {
#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 */
@@ -1289,6 +1631,9 @@ struct em_hw {
#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 */
@@ -1301,6 +1646,8 @@ struct em_hw {
#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 */
@@ -1327,6 +1674,34 @@ struct em_hw {
#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) */
@@ -1341,6 +1716,23 @@ struct em_hw {
#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 */
@@ -1354,6 +1746,8 @@ struct em_hw {
#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 */
@@ -1387,12 +1781,16 @@ struct em_hw {
#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 */
@@ -1411,6 +1809,7 @@ struct em_hw {
#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 */
@@ -1446,13 +1845,19 @@ struct em_hw {
#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 */
@@ -1463,11 +1868,97 @@ struct em_hw {
#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 {
+ em_mng_mode_none = 0,
+ em_mng_mode_asf,
+ em_mng_mode_pt,
+ em_mng_mode_ipmi,
+ em_mng_mode_host_interface_only
+} em_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 em_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 em_host_command_info {
+ struct em_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 */
@@ -1477,22 +1968,20 @@ struct em_hw {
/* 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 */
@@ -1606,7 +2095,22 @@ struct em_hw {
#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
@@ -1663,6 +2167,13 @@ struct em_hw {
/* 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. */
@@ -1760,6 +2271,7 @@ struct em_hw {
#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*/
@@ -1768,12 +2280,20 @@ struct em_hw {
#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
@@ -2058,20 +2578,30 @@ struct em_hw {
#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 */
@@ -2099,7 +2629,11 @@ struct em_hw {
#define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080
#define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500
+
/* Bit definitions for valid PHY IDs. */
+/* I = Integrated
+ * E = External
+ */
#define M88E1000_E_PHY_ID 0x01410C50
#define M88E1000_I_PHY_ID 0x01410C30
#define M88E1011_I_PHY_ID 0x01410C20
@@ -2107,6 +2641,8 @@ struct em_hw {
#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
diff --git a/sys/dev/em/if_em_osdep.h b/sys/dev/em/if_em_osdep.h
index 5c010ec..9d5bdc2 100644
--- a/sys/dev/em/if_em_osdep.h
+++ b/sys/dev/em/if_em_osdep.h
@@ -1,6 +1,6 @@
/**************************************************************************
-Copyright (c) 2001-2003, Intel Corporation
+Copyright (c) 2001-2005, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -60,6 +60,8 @@ POSSIBILITY OF SUCH DAMAGE.
/* The happy-fun DELAY macro is defined in /usr/src/sys/i386/include/clock.h */
#define usec_delay(x) DELAY(x)
#define msec_delay(x) DELAY(1000*(x))
+/* TODO: Should we be paranoid about delaying in interrupt context? */
+#define msec_delay_irq(x) DELAY(1000*(x))
#define MSGOUT(S, A, B) printf(S "\n", A, B)
#define DEBUGFUNC(F) DEBUGOUT(F);
@@ -117,8 +119,25 @@ struct em_osdep
#define E1000_READ_REG_ARRAY(hw, reg, index) \
E1000_READ_OFFSET(hw, E1000_REG_OFFSET(hw, reg) + ((index) << 2))
+#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
+
#define E1000_WRITE_REG_ARRAY(hw, reg, index, value) \
E1000_WRITE_OFFSET(hw, E1000_REG_OFFSET(hw, reg) + ((index) << 2), value)
+#define E1000_WRITE_REG_ARRAY_BYTE(hw, reg, index, value) \
+ bus_space_write_1( ((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \
+ ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \
+ E1000_REG_OFFSET(hw, reg) + (index), \
+ value)
+
+#define E1000_WRITE_REG_ARRAY_WORD(hw, reg, index, value) \
+ bus_space_write_2( ((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \
+ ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \
+ E1000_REG_OFFSET(hw, reg) + (index), \
+ value)
+
+#define E1000_WRITE_REG_ARRAY_DWORD(hw, reg, index, value) \
+ E1000_WRITE_OFFSET(hw, E1000_REG_OFFSET(hw, reg) + ((index) << 2), value)
+
#endif /* _FREEBSD_OS_H_ */
OpenPOWER on IntegriCloud