#include <dev/netif/em/if_em.h>
#define EM_NAME "Intel(R) PRO/1000 Network Connection "
-#define EM_VER " 6.9.6"
+#define EM_VER " 7.1.7"
#define _EM_DEVICE(id, ret) \
{ EM_VENDOR_ID, E1000_DEV_ID_##id, ret, EM_NAME #id EM_VER }
EM_EMX_DEVICE(82573E_IAMT),
EM_EMX_DEVICE(82573L),
+ EM_DEVICE(82583V),
+
EM_EMX_DEVICE(80003ES2LAN_COPPER_SPT),
EM_EMX_DEVICE(80003ES2LAN_SERDES_SPT),
EM_EMX_DEVICE(80003ES2LAN_COPPER_DPT),
EM_DEVICE(ICH8_IFE_GT),
EM_DEVICE(ICH8_IFE_G),
EM_DEVICE(ICH8_IGP_M),
+ EM_DEVICE(ICH8_82567V_3),
EM_DEVICE(ICH9_IGP_M_AMT),
EM_DEVICE(ICH9_IGP_AMT),
EM_DEVICE(ICH9_BM),
EM_EMX_DEVICE(82574L),
+ EM_EMX_DEVICE(82574LA),
EM_DEVICE(ICH10_R_BM_LM),
EM_DEVICE(ICH10_R_BM_LF),
EM_DEVICE(ICH10_R_BM_V),
EM_DEVICE(ICH10_D_BM_LM),
EM_DEVICE(ICH10_D_BM_LF),
+ EM_DEVICE(ICH10_D_BM_V),
+
+ EM_DEVICE(PCH_M_HV_LM),
+ EM_DEVICE(PCH_M_HV_LC),
+ EM_DEVICE(PCH_D_HV_DM),
+ EM_DEVICE(PCH_D_HV_DC),
+
+ EM_DEVICE(PCH2_LV_LM),
+ EM_DEVICE(PCH2_LV_V),
/* required last entry */
EM_DEVICE_NULL
static int em_is_valid_eaddr(const uint8_t *);
static int em_alloc_pci_res(struct adapter *);
static void em_free_pci_res(struct adapter *);
-static int em_hw_init(struct adapter *);
+static int em_reset(struct adapter *);
static void em_setup_ifp(struct adapter *);
static void em_init_tx_unit(struct adapter *);
static void em_init_rx_unit(struct adapter *);
static void em_set_multi(struct adapter *);
static void em_update_link_status(struct adapter *);
static void em_smartspeed(struct adapter *);
+static void em_set_itr(struct adapter *, uint32_t);
/* Hardware workarounds */
static int em_82547_fifo_workaround(struct adapter *, int);
struct ifnet *ifp = &adapter->arpcom.ac_if;
int tsize, rsize;
int error = 0;
- uint16_t eeprom_data, device_id;
+ uint16_t eeprom_data, device_id, apme_mask;
adapter->dev = adapter->osdep.dev = dev;
* and this must happen after the MAC is identified.
*/
if (adapter->hw.mac.type == e1000_ich8lan ||
+ adapter->hw.mac.type == e1000_ich9lan ||
adapter->hw.mac.type == e1000_ich10lan ||
- adapter->hw.mac.type == e1000_ich9lan) {
+ adapter->hw.mac.type == e1000_pchlan ||
+ adapter->hw.mac.type == e1000_pch2lan) {
adapter->flash_rid = EM_BAR_FLASH;
adapter->flash = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
}
adapter->rx_desc_base = adapter->rxdma.dma_vaddr;
+ /* Allocate multicast array memory. */
+ adapter->mta = kmalloc(ETH_ADDR_LEN * MAX_NUM_MULTICAST_ADDRESSES,
+ M_DEVBUF, M_WAITOK);
+
+ /* Indicate SOL/IDER usage */
+ if (e1000_check_reset_block(&adapter->hw)) {
+ device_printf(dev,
+ "PHY reset is blocked due to SOL/IDER session.\n");
+ }
+
+ /*
+ * Start from a known state, this is important in reading the
+ * nvm and mac from that.
+ */
+ e1000_reset_hw(&adapter->hw);
+
/* Make sure we have a good EEPROM before we read from it */
if (e1000_validate_nvm_checksum(&adapter->hw) < 0) {
/*
}
}
- /* Initialize the hardware */
- error = em_hw_init(adapter);
- if (error) {
- device_printf(dev, "Unable to initialize the hardware\n");
- goto fail;
- }
-
/* Copy the permanent MAC address out of the EEPROM */
if (e1000_read_mac_addr(&adapter->hw) < 0) {
device_printf(dev, "EEPROM read error while reading MAC"
/* Manually turn off all interrupts */
E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff);
- /* Setup OS specific network interface */
- em_setup_ifp(adapter);
-
- /* Add sysctl tree, must after em_setup_ifp() */
- em_add_sysctl(adapter);
-
- /* Initialize statistics */
- em_update_stats(adapter);
-
- adapter->hw.mac.get_link_status = 1;
- em_update_link_status(adapter);
-
- /* Indicate SOL/IDER usage */
- if (e1000_check_reset_block(&adapter->hw)) {
- device_printf(dev,
- "PHY reset is blocked due to SOL/IDER session.\n");
- }
-
/* Determine if we have to control management hardware */
adapter->has_manage = e1000_enable_mng_pass_thru(&adapter->hw);
/*
* Setup Wake-on-Lan
*/
+ apme_mask = EM_EEPROM_APME;
+ eeprom_data = 0;
switch (adapter->hw.mac.type) {
case e1000_82542:
case e1000_82543:
break;
+ case e1000_82573:
+ case e1000_82583:
+ adapter->has_amt = 1;
+ /* FALL THROUGH */
+
case e1000_82546:
case e1000_82546_rev_3:
case e1000_82571:
+ case e1000_82572:
case e1000_80003es2lan:
if (adapter->hw.bus.func == 1) {
e1000_read_nvm(&adapter->hw,
e1000_read_nvm(&adapter->hw,
NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
}
- eeprom_data &= EM_EEPROM_APME;
+ break;
+
+ case e1000_ich8lan:
+ case e1000_ich9lan:
+ case e1000_ich10lan:
+ case e1000_pchlan:
+ case e1000_pch2lan:
+ apme_mask = E1000_WUC_APME;
+ adapter->has_amt = TRUE;
+ eeprom_data = E1000_READ_REG(&adapter->hw, E1000_WUC);
break;
default:
- /* APME bit in EEPROM is mapped to WUC.APME */
- eeprom_data =
- E1000_READ_REG(&adapter->hw, E1000_WUC) & E1000_WUC_APME;
+ e1000_read_nvm(&adapter->hw,
+ NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
break;
}
- if (eeprom_data)
- adapter->wol = E1000_WUFC_MAG;
+ if (eeprom_data & apme_mask)
+ adapter->wol = E1000_WUFC_MAG | E1000_WUFC_MC;
+
/*
* We have the eeprom settings, now apply the special cases
* where the eeprom may be wrong or the board won't support
/* XXX disable wol */
adapter->wol = 0;
+ /* Setup OS specific network interface */
+ em_setup_ifp(adapter);
+
+ /* Add sysctl tree, must after em_setup_ifp() */
+ em_add_sysctl(adapter);
+
+ /* Reset the hardware */
+ error = em_reset(adapter);
+ if (error) {
+ device_printf(dev, "Unable to reset the hardware\n");
+ goto fail;
+ }
+
+ /* Initialize statistics */
+ em_update_stats(adapter);
+
+ adapter->hw.mac.get_link_status = 1;
+ em_update_link_status(adapter);
+
/* Do we need workaround for 82544 PCI-X adapter? */
if (adapter->hw.bus.type == e1000_bus_type_pcix &&
adapter->hw.mac.type == e1000_82544)
if (adapter->tx_int_nsegs < adapter->oact_tx_desc)
adapter->tx_int_nsegs = adapter->oact_tx_desc;
+ /* Non-AMT based hardware can now take control from firmware */
+ if (adapter->has_manage && !adapter->has_amt &&
+ adapter->hw.mac.type >= e1000_82571)
+ em_get_hw_control(adapter);
+
error = bus_setup_intr(dev, adapter->intr_res, INTR_MPSAFE,
em_intr, adapter, &adapter->intr_tag,
ifp->if_serializer);
e1000_phy_hw_reset(&adapter->hw);
em_rel_mgmt(adapter);
-
- if ((adapter->hw.mac.type == e1000_82573 ||
- adapter->hw.mac.type == e1000_ich8lan ||
- adapter->hw.mac.type == e1000_ich10lan ||
- adapter->hw.mac.type == e1000_ich9lan) &&
- e1000_check_mng_mode(&adapter->hw))
- em_rel_hw_control(adapter);
+ em_rel_hw_control(adapter);
if (adapter->wol) {
E1000_WRITE_REG(&adapter->hw, E1000_WUC,
lwkt_serialize_exit(ifp->if_serializer);
ether_ifdetach(ifp);
+ } else {
+ em_rel_hw_control(adapter);
}
bus_generic_detach(dev);
em_stop(adapter);
em_rel_mgmt(adapter);
+ em_rel_hw_control(adapter);
- if ((adapter->hw.mac.type == e1000_82573 ||
- adapter->hw.mac.type == e1000_ich8lan ||
- adapter->hw.mac.type == e1000_ich10lan ||
- adapter->hw.mac.type == e1000_ich9lan) &&
- e1000_check_mng_mode(&adapter->hw))
- em_rel_hw_control(adapter);
-
- if (adapter->wol) {
+ if (adapter->wol) {
E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN);
E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol);
em_enable_wol(dev);
- }
+ }
lwkt_serialize_exit(ifp->if_serializer);
case e1000_82572:
case e1000_ich9lan:
case e1000_ich10lan:
+ case e1000_pch2lan:
case e1000_82574:
case e1000_80003es2lan:
max_frame_size = 9234;
break;
+ case e1000_pchlan:
+ max_frame_size = 4096;
+ break;
+
/* Adapters that do not support jumbo frames */
case e1000_82542:
+ case e1000_82583:
case e1000_ich8lan:
max_frame_size = ETHER_MAX_LEN;
break;
break;
case e1000_82574:
+ case e1000_82583:
pba = E1000_PBA_20K; /* 20K for Rx, 20K for Tx */
break;
+ case e1000_ich8lan:
+ pba = E1000_PBA_8K;
+ break;
+
case e1000_ich9lan:
case e1000_ich10lan:
#define E1000_PBA_10K 0x000A
pba = E1000_PBA_10K;
break;
- case e1000_ich8lan:
- pba = E1000_PBA_8K;
+ case e1000_pchlan:
+ case e1000_pch2lan:
+ pba = E1000_PBA_26K;
break;
default:
E1000_RAR_ENTRIES - 1);
}
- /* Initialize the hardware */
- if (em_hw_init(adapter)) {
- device_printf(dev, "Unable to initialize the hardware\n");
+ /* Reset the hardware */
+ if (em_reset(adapter)) {
+ device_printf(dev, "Unable to reset the hardware\n");
/* XXX em_stop()? */
return;
}
tmp |= E1000_CTRL_EXT_PBA_CLR;
E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, tmp);
/*
+ * XXX MSIX
* Set the IVAR - interrupt vector routing.
* Each nibble represents a vector, high bit
* is enable, other 3 bits are the MSIX table
#endif /* DEVICE_POLLING */
em_enable_intr(adapter);
+ /* AMT based hardware can now take control from firmware */
+ if (adapter->has_manage && adapter->has_amt &&
+ adapter->hw.mac.type >= e1000_82571)
+ em_get_hw_control(adapter);
+
/* Don't reset the phy next time init gets called */
adapter->hw.phy.reset_disable = TRUE;
}
struct ifnet *ifp = &adapter->arpcom.ac_if;
struct ifmultiaddr *ifma;
uint32_t reg_rctl = 0;
- uint8_t mta[512]; /* Largest MTS is 4096 bits */
+ uint8_t *mta;
int mcnt = 0;
+ mta = adapter->mta;
+ bzero(mta, ETH_ADDR_LEN * MAX_NUM_MULTICAST_ADDRESSES);
+
if (adapter->hw.mac.type == e1000_82542 &&
adapter->hw.revision_id == E1000_REVISION_2) {
reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
* Check if we should enable/disable SPEED_MODE bit on
* 82571/82572
*/
- if (hw->mac.type == e1000_82571 ||
- hw->mac.type == e1000_82572) {
+ if (adapter->link_speed != SPEED_1000 &&
+ (hw->mac.type == e1000_82571 ||
+ hw->mac.type == e1000_82572)) {
int tarc0;
tarc0 = E1000_READ_REG(hw, E1000_TARC(0));
- if (adapter->link_speed != SPEED_1000)
- tarc0 &= ~SPEED_MODE_BIT;
- else
- tarc0 |= SPEED_MODE_BIT;
+ tarc0 &= ~SPEED_MODE_BIT;
E1000_WRITE_REG(hw, E1000_TARC(0), tarc0);
}
if (bootverbose) {
}
static int
-em_hw_init(struct adapter *adapter)
+em_reset(struct adapter *adapter)
{
device_t dev = adapter->dev;
uint16_t rx_buffer_size;
- /* Issue a global reset */
- e1000_reset_hw(&adapter->hw);
-
- /* Get control from any management/hw control */
- if ((adapter->hw.mac.type == e1000_82573 ||
- adapter->hw.mac.type == e1000_ich8lan ||
- adapter->hw.mac.type == e1000_ich10lan ||
- adapter->hw.mac.type == e1000_ich9lan) &&
- e1000_check_mng_mode(&adapter->hw))
- em_get_hw_control(adapter);
-
/* When hardware is reset, fifo_head is also reset */
adapter->tx_fifo_head = 0;
adapter->hw.fc.pause_time = 0xFFFF;
else
adapter->hw.fc.pause_time = EM_FC_PAUSE_TIME;
+
adapter->hw.fc.send_xon = TRUE;
+
adapter->hw.fc.requested_mode = e1000_fc_full;
+ /* Workaround: no TX flow ctrl for PCH */
+ if (adapter->hw.mac.type == e1000_pchlan)
+ adapter->hw.fc.requested_mode = e1000_fc_rx_pause;
+
+ /* Override - settings for PCH2LAN, ya its magic :) */
+ if (adapter->hw.mac.type == e1000_pch2lan) {
+ adapter->hw.fc.high_water = 0x5C20;
+ adapter->hw.fc.low_water = 0x5048;
+ adapter->hw.fc.pause_time = 0x0650;
+ adapter->hw.fc.refresh_time = 0x0400;
+
+ /* Jumbos need adjusted PBA */
+ if (adapter->arpcom.ac_if.if_mtu > ETHERMTU)
+ E1000_WRITE_REG(&adapter->hw, E1000_PBA, 12);
+ else
+ E1000_WRITE_REG(&adapter->hw, E1000_PBA, 26);
+ }
+
+ /* Issue a global reset */
+ e1000_reset_hw(&adapter->hw);
+ if (adapter->hw.mac.type >= e1000_82544)
+ E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0);
+
if (e1000_init_hw(&adapter->hw) < 0) {
device_printf(dev, "Hardware Initialization Failed\n");
return (EIO);
}
+ E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN);
+ e1000_get_phy_info(&adapter->hw);
e1000_check_for_link(&adapter->hw);
return (0);
{
struct ifnet *ifp = &adapter->arpcom.ac_if;
uint64_t bus_addr;
- uint32_t rctl, rxcsum;
+ uint32_t rctl;
/*
* Make sure receives are disabled while setting
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
if (adapter->hw.mac.type >= e1000_82540) {
+ uint32_t itr;
+
/*
* Set the interrupt throttling rate. Value is calculated
* as ITR = 1 / (INT_THROTTLE_CEIL * 256ns)
*/
- if (adapter->int_throttle_ceil) {
- E1000_WRITE_REG(&adapter->hw, E1000_ITR,
- 1000000000 / 256 / adapter->int_throttle_ceil);
- } else {
- E1000_WRITE_REG(&adapter->hw, E1000_ITR, 0);
- }
+ if (adapter->int_throttle_ceil)
+ itr = 1000000000 / 256 / adapter->int_throttle_ceil;
+ else
+ itr = 0;
+ em_set_itr(adapter, itr);
}
/* Disable accelerated ackknowledge */
E1000_RFCTL, E1000_RFCTL_ACK_DIS);
}
- /* Setup the Base and Length of the Rx Descriptor Ring */
+ /* Receive Checksum Offload for TCP and UDP */
+ if (ifp->if_capenable & IFCAP_RXCSUM) {
+ uint32_t rxcsum;
+
+ rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM);
+ rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL);
+ E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, rxcsum);
+ }
+
+ /*
+ * XXX TEMPORARY WORKAROUND: on some systems with 82573
+ * long latencies are observed, like Lenovo X60. This
+ * change eliminates the problem, but since having positive
+ * values in RDTR is a known source of problems on other
+ * platforms another solution is being sought.
+ */
+ if (em_82573_workaround && adapter->hw.mac.type == e1000_82573) {
+ E1000_WRITE_REG(&adapter->hw, E1000_RADV, EM_RADV_82573);
+ E1000_WRITE_REG(&adapter->hw, E1000_RDTR, EM_RDTR_82573);
+ }
+
+ /*
+ * Setup the Base and Length of the Rx Descriptor Ring
+ */
bus_addr = adapter->rxdma.dma_paddr;
E1000_WRITE_REG(&adapter->hw, E1000_RDLEN(0),
adapter->num_rx_desc * sizeof(struct e1000_rx_desc));
E1000_WRITE_REG(&adapter->hw, E1000_RDBAL(0),
(uint32_t)bus_addr);
+ /*
+ * Setup the HW Rx Head and Tail Descriptor Pointers
+ */
+ E1000_WRITE_REG(&adapter->hw, E1000_RDH(0), 0);
+ E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), adapter->num_rx_desc - 1);
+
+ /* Set early receive threshold on appropriate hw */
+ if (((adapter->hw.mac.type == e1000_ich9lan) ||
+ (adapter->hw.mac.type == e1000_pch2lan) ||
+ (adapter->hw.mac.type == e1000_ich10lan)) &&
+ (ifp->if_mtu > ETHERMTU)) {
+ uint32_t rxdctl;
+
+ rxdctl = E1000_READ_REG(&adapter->hw, E1000_RXDCTL(0));
+ E1000_WRITE_REG(&adapter->hw, E1000_RXDCTL(0), rxdctl | 3);
+ E1000_WRITE_REG(&adapter->hw, E1000_ERT, 0x100 | (1 << 13));
+ }
+
+ if (adapter->hw.mac.type == e1000_pch2lan) {
+ if (ifp->if_mtu > ETHERMTU)
+ e1000_lv_jumbo_workaround_ich8lan(&adapter->hw, TRUE);
+ else
+ e1000_lv_jumbo_workaround_ich8lan(&adapter->hw, FALSE);
+ }
+
/* Setup the Receive Control Register */
rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
else
rctl &= ~E1000_RCTL_LPE;
- /* Receive Checksum Offload for TCP and UDP */
- if (ifp->if_capenable & IFCAP_RXCSUM) {
- rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM);
- rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL);
- E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, rxcsum);
- }
-
- /*
- * XXX TEMPORARY WORKAROUND: on some systems with 82573
- * long latencies are observed, like Lenovo X60. This
- * change eliminates the problem, but since having positive
- * values in RDTR is a known source of problems on other
- * platforms another solution is being sought.
- */
- if (em_82573_workaround && adapter->hw.mac.type == e1000_82573) {
- E1000_WRITE_REG(&adapter->hw, E1000_RADV, EM_RADV_82573);
- E1000_WRITE_REG(&adapter->hw, E1000_RDTR, EM_RDTR_82573);
- }
-
- /*
- * Setup the HW Rx Head and Tail Descriptor Pointers
- */
- E1000_WRITE_REG(&adapter->hw, E1000_RDH(0), 0);
- E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), adapter->num_rx_desc - 1);
-
/* Enable Receives */
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl);
}
static void
em_enable_intr(struct adapter *adapter)
{
+ uint32_t ims_mask = IMS_ENABLE_MASK;
+
lwkt_serialize_handler_enable(adapter->arpcom.ac_if.if_serializer);
- E1000_WRITE_REG(&adapter->hw, E1000_IMS, IMS_ENABLE_MASK);
+
+#if 0
+ /* XXX MSIX */
+ if (adapter->hw.mac.type == e1000_82574) {
+ E1000_WRITE_REG(&adapter->hw, EM_EIAC, EM_MSIX_MASK);
+ ims_mask |= EM_MSIX_MASK;
+ }
+#endif
+ E1000_WRITE_REG(&adapter->hw, E1000_IMS, ims_mask);
}
static void
if (adapter->hw.mac.type == e1000_82542 &&
adapter->hw.revision_id == E1000_REVISION_2)
clear &= ~E1000_IMC_RXSEQ;
+ else if (adapter->hw.mac.type == e1000_82574)
+ E1000_WRITE_REG(&adapter->hw, EM_EIAC, 0);
E1000_WRITE_REG(&adapter->hw, E1000_IMC, clear);
static void
em_get_hw_control(struct adapter *adapter)
{
- uint32_t ctrl_ext, swsm;
-
/* Let firmware know the driver has taken over */
- switch (adapter->hw.mac.type) {
- case e1000_82573:
+ if (adapter->hw.mac.type == e1000_82573) {
+ uint32_t swsm;
+
swsm = E1000_READ_REG(&adapter->hw, E1000_SWSM);
E1000_WRITE_REG(&adapter->hw, E1000_SWSM,
swsm | E1000_SWSM_DRV_LOAD);
- break;
- case e1000_82571:
- case e1000_82572:
- case e1000_80003es2lan:
- case e1000_ich8lan:
- case e1000_ich9lan:
- case e1000_ich10lan:
+ } else {
+ uint32_t ctrl_ext;
+
ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT,
ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
- break;
- default:
- break;
}
+ adapter->control_hw = 1;
}
/*
static void
em_rel_hw_control(struct adapter *adapter)
{
- uint32_t ctrl_ext, swsm;
+ if (!adapter->control_hw)
+ return;
+ adapter->control_hw = 0;
/* Let firmware taken over control of h/w */
- switch (adapter->hw.mac.type) {
- case e1000_82573:
+ if (adapter->hw.mac.type == e1000_82573) {
+ uint32_t swsm;
+
swsm = E1000_READ_REG(&adapter->hw, E1000_SWSM);
E1000_WRITE_REG(&adapter->hw, E1000_SWSM,
swsm & ~E1000_SWSM_DRV_LOAD);
- break;
+ } else {
+ uint32_t ctrl_ext;
- case e1000_82571:
- case e1000_82572:
- case e1000_80003es2lan:
- case e1000_ich8lan:
- case e1000_ich9lan:
- case e1000_ich10lan:
ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT,
ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
- break;
-
- default:
- break;
}
}
adapter->int_throttle_ceil = 0;
if (ifp->if_flags & IFF_RUNNING)
- E1000_WRITE_REG(&adapter->hw, E1000_ITR, throttle);
+ em_set_itr(adapter, throttle);
lwkt_serialize_exit(ifp->if_serializer);
return error;
}
+
+static void
+em_set_itr(struct adapter *adapter, uint32_t itr)
+{
+ E1000_WRITE_REG(&adapter->hw, E1000_ITR, itr);
+ if (adapter->hw.mac.type == e1000_82574) {
+ int i;
+
+ /*
+ * When using MSIX interrupts we need to
+ * throttle using the EITR register
+ */
+ for (i = 0; i < 4; ++i) {
+ E1000_WRITE_REG(&adapter->hw,
+ E1000_EITR_82574(i), itr);
+ }
+ }
+}
EMX_DEVICE(80003ES2LAN_SERDES_DPT),
EMX_DEVICE(82574L),
+ EMX_DEVICE(82574LA),
/* required last entry */
EMX_DEVICE_NULL
uint32_t *, uint32_t *);
static int emx_is_valid_eaddr(const uint8_t *);
-static int emx_hw_init(struct emx_softc *);
+static int emx_reset(struct emx_softc *);
static void emx_setup_ifp(struct emx_softc *);
static void emx_init_tx_unit(struct emx_softc *);
static void emx_init_rx_unit(struct emx_softc *);
static void emx_set_multi(struct emx_softc *);
static void emx_update_link_status(struct emx_softc *);
static void emx_smartspeed(struct emx_softc *);
+static void emx_set_itr(struct emx_softc *, uint32_t);
static void emx_print_debug_info(struct emx_softc *);
static void emx_print_nvm_info(struct emx_softc *);
struct emx_softc *sc = device_get_softc(dev);
struct ifnet *ifp = &sc->arpcom.ac_if;
int error = 0, i;
- uint16_t eeprom_data, device_id;
+ uint16_t eeprom_data, device_id, apme_mask;
lwkt_serialize_init(&sc->main_serialize);
lwkt_serialize_init(&sc->tx_serialize);
if (error)
goto fail;
+ /* Allocate multicast array memory. */
+ sc->mta = kmalloc(ETH_ADDR_LEN * EMX_MCAST_ADDR_MAX,
+ M_DEVBUF, M_WAITOK);
+
+ /* Indicate SOL/IDER usage */
+ if (e1000_check_reset_block(&sc->hw)) {
+ device_printf(dev,
+ "PHY reset is blocked due to SOL/IDER session.\n");
+ }
+
+ /*
+ * Start from a known state, this is important in reading the
+ * nvm and mac from that.
+ */
+ e1000_reset_hw(&sc->hw);
+
/* Make sure we have a good EEPROM before we read from it */
if (e1000_validate_nvm_checksum(&sc->hw) < 0) {
/*
}
}
- /* Initialize the hardware */
- error = emx_hw_init(sc);
- if (error) {
- device_printf(dev, "Unable to initialize the hardware\n");
- goto fail;
- }
-
/* Copy the permanent MAC address out of the EEPROM */
if (e1000_read_mac_addr(&sc->hw) < 0) {
device_printf(dev, "EEPROM read error while reading MAC"
goto fail;
}
- /* Manually turn off all interrupts */
- E1000_WRITE_REG(&sc->hw, E1000_IMC, 0xffffffff);
-
- /* Setup OS specific network interface */
- emx_setup_ifp(sc);
-
- /* Add sysctl tree, must after emx_setup_ifp() */
- emx_add_sysctl(sc);
-
- /* Initialize statistics */
- emx_update_stats(sc);
-
- sc->hw.mac.get_link_status = 1;
- emx_update_link_status(sc);
-
- /* Indicate SOL/IDER usage */
- if (e1000_check_reset_block(&sc->hw)) {
- device_printf(dev,
- "PHY reset is blocked due to SOL/IDER session.\n");
- }
-
/* Determine if we have to control management hardware */
sc->has_manage = e1000_enable_mng_pass_thru(&sc->hw);
/*
* Setup Wake-on-Lan
*/
+ apme_mask = EMX_EEPROM_APME;
+ eeprom_data = 0;
switch (sc->hw.mac.type) {
+ case e1000_82573:
+ sc->has_amt = 1;
+ /* FALL THROUGH */
+
case e1000_82571:
+ case e1000_82572:
case e1000_80003es2lan:
if (sc->hw.bus.func == 1) {
e1000_read_nvm(&sc->hw,
e1000_read_nvm(&sc->hw,
NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
}
- eeprom_data &= EMX_EEPROM_APME;
break;
default:
- /* APME bit in EEPROM is mapped to WUC.APME */
- eeprom_data =
- E1000_READ_REG(&sc->hw, E1000_WUC) & E1000_WUC_APME;
+ e1000_read_nvm(&sc->hw,
+ NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
break;
}
- if (eeprom_data)
- sc->wol = E1000_WUFC_MAG;
+ if (eeprom_data & apme_mask)
+ sc->wol = E1000_WUFC_MAG | E1000_WUFC_MC;
+
/*
* We have the eeprom settings, now apply the special cases
* where the eeprom may be wrong or the board won't support
/* XXX disable wol */
sc->wol = 0;
+ /* Setup OS specific network interface */
+ emx_setup_ifp(sc);
+
+ /* Add sysctl tree, must after em_setup_ifp() */
+ emx_add_sysctl(sc);
+
+ /* Reset the hardware */
+ error = emx_reset(sc);
+ if (error) {
+ device_printf(dev, "Unable to reset the hardware\n");
+ goto fail;
+ }
+
+ /* Initialize statistics */
+ emx_update_stats(sc);
+
+ sc->hw.mac.get_link_status = 1;
+ emx_update_link_status(sc);
+
sc->spare_tx_desc = EMX_TX_SPARE;
/*
if (sc->tx_int_nsegs < sc->oact_tx_desc)
sc->tx_int_nsegs = sc->oact_tx_desc;
+ /* Non-AMT based hardware can now take control from firmware */
+ if (sc->has_manage && !sc->has_amt)
+ emx_get_hw_control(sc);
+
error = bus_setup_intr(dev, sc->intr_res, INTR_MPSAFE, emx_intr, sc,
&sc->intr_tag, &sc->main_serialize);
if (error) {
e1000_phy_hw_reset(&sc->hw);
emx_rel_mgmt(sc);
-
- if (sc->hw.mac.type == e1000_82573 &&
- e1000_check_mng_mode(&sc->hw))
- emx_rel_hw_control(sc);
+ emx_rel_hw_control(sc);
if (sc->wol) {
E1000_WRITE_REG(&sc->hw, E1000_WUC, E1000_WUC_PME_EN);
ifnet_deserialize_all(ifp);
ether_ifdetach(ifp);
+ } else {
+ emx_rel_hw_control(sc);
}
bus_generic_detach(dev);
emx_stop(sc);
emx_rel_mgmt(sc);
+ emx_rel_hw_control(sc);
- if (sc->hw.mac.type == e1000_82573 &&
- e1000_check_mng_mode(&sc->hw))
- emx_rel_hw_control(sc);
-
- if (sc->wol) {
+ if (sc->wol) {
E1000_WRITE_REG(&sc->hw, E1000_WUC, E1000_WUC_PME_EN);
E1000_WRITE_REG(&sc->hw, E1000_WUFC, sc->wol);
emx_enable_wol(dev);
- }
+ }
ifnet_deserialize_all(ifp);
}
/* Initialize the hardware */
- if (emx_hw_init(sc)) {
- device_printf(dev, "Unable to initialize the hardware\n");
+ if (emx_reset(sc)) {
+ device_printf(dev, "Unable to reset the hardware\n");
/* XXX emx_stop()? */
return;
}
tmp |= E1000_CTRL_EXT_PBA_CLR;
E1000_WRITE_REG(&sc->hw, E1000_CTRL_EXT, tmp);
/*
+ * XXX MSIX
* Set the IVAR - interrupt vector routing.
* Each nibble represents a vector, high bit
* is enable, other 3 bits are the MSIX table
#endif /* IFPOLL_ENABLE */
emx_enable_intr(sc);
+ /* AMT based hardware can now take control from firmware */
+ if (sc->has_manage && sc->has_amt)
+ emx_get_hw_control(sc);
+
/* Don't reset the phy next time init gets called */
sc->hw.phy.reset_disable = TRUE;
}
struct ifnet *ifp = &sc->arpcom.ac_if;
struct ifmultiaddr *ifma;
uint32_t reg_rctl = 0;
- uint8_t mta[512]; /* Largest MTS is 4096 bits */
+ uint8_t *mta;
int mcnt = 0;
+ mta = sc->mta;
+ bzero(mta, ETH_ADDR_LEN * EMX_MCAST_ADDR_MAX);
+
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
* Check if we should enable/disable SPEED_MODE bit on
* 82571EB/82572EI
*/
- if (hw->mac.type == e1000_82571 ||
- hw->mac.type == e1000_82572) {
+ if (sc->link_speed != SPEED_1000 &&
+ (hw->mac.type == e1000_82571 ||
+ hw->mac.type == e1000_82572)) {
int tarc0;
tarc0 = E1000_READ_REG(hw, E1000_TARC(0));
- if (sc->link_speed != SPEED_1000)
- tarc0 &= ~EMX_TARC_SPEED_MODE;
- else
- tarc0 |= EMX_TARC_SPEED_MODE;
+ tarc0 &= ~EMX_TARC_SPEED_MODE;
E1000_WRITE_REG(hw, E1000_TARC(0), tarc0);
}
if (bootverbose) {
}
static int
-emx_hw_init(struct emx_softc *sc)
+emx_reset(struct emx_softc *sc)
{
device_t dev = sc->dev;
uint16_t rx_buffer_size;
- /* Issue a global reset */
- e1000_reset_hw(&sc->hw);
-
- /* Get control from any management/hw control */
- if (sc->hw.mac.type == e1000_82573 &&
- e1000_check_mng_mode(&sc->hw))
- emx_get_hw_control(sc);
-
/* Set up smart power down as default off on newer adapters. */
if (!emx_smart_pwr_down &&
(sc->hw.mac.type == e1000_82571 ||
sc->hw.fc.send_xon = TRUE;
sc->hw.fc.requested_mode = e1000_fc_full;
+ /* Issue a global reset */
+ e1000_reset_hw(&sc->hw);
+ E1000_WRITE_REG(&sc->hw, E1000_WUC, 0);
+
if (e1000_init_hw(&sc->hw) < 0) {
device_printf(dev, "Hardware Initialization Failed\n");
return (EIO);
}
+ E1000_WRITE_REG(&sc->hw, E1000_VET, ETHERTYPE_VLAN);
+ e1000_get_phy_info(&sc->hw);
e1000_check_for_link(&sc->hw);
return (0);
{
struct ifnet *ifp = &sc->arpcom.ac_if;
uint64_t bus_addr;
- uint32_t rctl, rxcsum, rfctl;
+ uint32_t rctl, itr, rfctl;
int i;
/*
* Set the interrupt throttling rate. Value is calculated
* as ITR = 1 / (INT_THROTTLE_CEIL * 256ns)
*/
- if (sc->int_throttle_ceil) {
- E1000_WRITE_REG(&sc->hw, E1000_ITR,
- 1000000000 / 256 / sc->int_throttle_ceil);
- } else {
- E1000_WRITE_REG(&sc->hw, E1000_ITR, 0);
- }
+ if (sc->int_throttle_ceil)
+ itr = 1000000000 / 256 / sc->int_throttle_ceil;
+ else
+ itr = 0;
+ emx_set_itr(sc, itr);
/* Use extended RX descriptor */
rfctl = E1000_RFCTL_EXTEN;
E1000_WRITE_REG(&sc->hw, E1000_RFCTL, rfctl);
- /* Setup the Base and Length of the Rx Descriptor Ring */
- for (i = 0; i < sc->rx_ring_inuse; ++i) {
- struct emx_rxdata *rdata = &sc->rx_data[i];
-
- bus_addr = rdata->rx_desc_paddr;
- E1000_WRITE_REG(&sc->hw, E1000_RDLEN(i),
- rdata->num_rx_desc * sizeof(emx_rxdesc_t));
- E1000_WRITE_REG(&sc->hw, E1000_RDBAH(i),
- (uint32_t)(bus_addr >> 32));
- E1000_WRITE_REG(&sc->hw, E1000_RDBAL(i),
- (uint32_t)bus_addr);
- }
-
- /* Setup the Receive Control Register */
- rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
- rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
- E1000_RCTL_RDMTS_HALF | E1000_RCTL_SECRC |
- (sc->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
-
- /* Make sure VLAN Filters are off */
- rctl &= ~E1000_RCTL_VFE;
-
- /* Don't store bad paket */
- rctl &= ~E1000_RCTL_SBP;
-
- /* MCLBYTES */
- rctl |= E1000_RCTL_SZ_2048;
-
- if (ifp->if_mtu > ETHERMTU)
- rctl |= E1000_RCTL_LPE;
- else
- rctl &= ~E1000_RCTL_LPE;
-
/*
* Receive Checksum Offload for TCP and UDP
*
* packet type.
*/
if (ifp->if_capenable & (IFCAP_RSS | IFCAP_RXCSUM)) {
+ uint32_t rxcsum;
+
rxcsum = E1000_READ_REG(&sc->hw, E1000_RXCSUM);
/*
E1000_WRITE_REG(&sc->hw, E1000_RDTR, EMX_RDTR_82573);
}
- /*
- * Setup the HW Rx Head and Tail Descriptor Pointers
- */
for (i = 0; i < sc->rx_ring_inuse; ++i) {
+ struct emx_rxdata *rdata = &sc->rx_data[i];
+
+ /*
+ * Setup the Base and Length of the Rx Descriptor Ring
+ */
+ bus_addr = rdata->rx_desc_paddr;
+ E1000_WRITE_REG(&sc->hw, E1000_RDLEN(i),
+ rdata->num_rx_desc * sizeof(emx_rxdesc_t));
+ E1000_WRITE_REG(&sc->hw, E1000_RDBAH(i),
+ (uint32_t)(bus_addr >> 32));
+ E1000_WRITE_REG(&sc->hw, E1000_RDBAL(i),
+ (uint32_t)bus_addr);
+
+ /*
+ * Setup the HW Rx Head and Tail Descriptor Pointers
+ */
E1000_WRITE_REG(&sc->hw, E1000_RDH(i), 0);
E1000_WRITE_REG(&sc->hw, E1000_RDT(i),
sc->rx_data[i].num_rx_desc - 1);
}
+ /* Setup the Receive Control Register */
+ rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
+ rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
+ E1000_RCTL_RDMTS_HALF | E1000_RCTL_SECRC |
+ (sc->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
+
+ /* Make sure VLAN Filters are off */
+ rctl &= ~E1000_RCTL_VFE;
+
+ /* Don't store bad paket */
+ rctl &= ~E1000_RCTL_SBP;
+
+ /* MCLBYTES */
+ rctl |= E1000_RCTL_SZ_2048;
+
+ if (ifp->if_mtu > ETHERMTU)
+ rctl |= E1000_RCTL_LPE;
+ else
+ rctl &= ~E1000_RCTL_LPE;
+
/* Enable Receives */
E1000_WRITE_REG(&sc->hw, E1000_RCTL, rctl);
}
static void
emx_enable_intr(struct emx_softc *sc)
{
+ uint32_t ims_mask = IMS_ENABLE_MASK;
+
lwkt_serialize_handler_enable(&sc->main_serialize);
- E1000_WRITE_REG(&sc->hw, E1000_IMS, IMS_ENABLE_MASK);
+
+#if 0
+ if (sc->hw.mac.type == e1000_82574) {
+ E1000_WRITE_REG(hw, EMX_EIAC, EM_MSIX_MASK);
+ ims_mask |= EM_MSIX_MASK;
+ }
+#endif
+ E1000_WRITE_REG(&sc->hw, E1000_IMS, ims_mask);
}
static void
emx_disable_intr(struct emx_softc *sc)
{
+ if (sc->hw.mac.type == e1000_82574)
+ E1000_WRITE_REG(&sc->hw, EMX_EIAC, 0);
E1000_WRITE_REG(&sc->hw, E1000_IMC, 0xffffffff);
+
lwkt_serialize_handler_disable(&sc->main_serialize);
}
static void
emx_get_hw_control(struct emx_softc *sc)
{
- uint32_t ctrl_ext, swsm;
-
/* Let firmware know the driver has taken over */
- switch (sc->hw.mac.type) {
- case e1000_82573:
+ if (sc->hw.mac.type == e1000_82573) {
+ uint32_t swsm;
+
swsm = E1000_READ_REG(&sc->hw, E1000_SWSM);
E1000_WRITE_REG(&sc->hw, E1000_SWSM,
swsm | E1000_SWSM_DRV_LOAD);
- break;
+ } else {
+ uint32_t ctrl_ext;
- case e1000_82571:
- case e1000_82572:
- case e1000_80003es2lan:
ctrl_ext = E1000_READ_REG(&sc->hw, E1000_CTRL_EXT);
E1000_WRITE_REG(&sc->hw, E1000_CTRL_EXT,
ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
- break;
-
- default:
- break;
}
+ sc->control_hw = 1;
}
/*
static void
emx_rel_hw_control(struct emx_softc *sc)
{
- uint32_t ctrl_ext, swsm;
+ if (!sc->control_hw)
+ return;
+ sc->control_hw = 0;
/* Let firmware taken over control of h/w */
- switch (sc->hw.mac.type) {
- case e1000_82573:
+ if (sc->hw.mac.type == e1000_82573) {
+ uint32_t swsm;
+
swsm = E1000_READ_REG(&sc->hw, E1000_SWSM);
E1000_WRITE_REG(&sc->hw, E1000_SWSM,
swsm & ~E1000_SWSM_DRV_LOAD);
- break;
+ } else {
+ uint32_t ctrl_ext;
- case e1000_82571:
- case e1000_82572:
- case e1000_80003es2lan:
ctrl_ext = E1000_READ_REG(&sc->hw, E1000_CTRL_EXT);
E1000_WRITE_REG(&sc->hw, E1000_CTRL_EXT,
ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
- break;
-
- default:
- break;
}
}
sc->int_throttle_ceil = 0;
if (ifp->if_flags & IFF_RUNNING)
- E1000_WRITE_REG(&sc->hw, E1000_ITR, throttle);
+ emx_set_itr(sc, throttle);
ifnet_deserialize_all(ifp);
}
#endif /* IFPOLL_ENABLE */
+
+static void
+emx_set_itr(struct emx_softc *sc, uint32_t itr)
+{
+ E1000_WRITE_REG(&sc->hw, E1000_ITR, itr);
+ if (sc->hw.mac.type == e1000_82574) {
+ int i;
+
+ /*
+ * When using MSIX interrupts we need to
+ * throttle using the EITR register
+ */
+ for (i = 0; i < 4; ++i)
+ E1000_WRITE_REG(&sc->hw, E1000_EITR_82574(i), itr);
+ }
+}