summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2016-02-18 14:24:40 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2016-02-18 14:24:40 +0000
commitef60c32981b2ef95022bea98316a00380b1e4bfa (patch)
tree50ee377b1edcd6822e94869035f09b4d0d67b001
parent267979ccbc324ccd5a8fc578f1966c37cf895d81 (diff)
Add support for the Intel i219 network chip to the em(4) driver.
from Christian Ehrhardt; input jsg@; OK deraadt@ sthen@ mpi@ jsg@ tested by sthen@ jca@ benno@ bluhm@
-rw-r--r--sys/dev/pci/if_em.c182
-rw-r--r--sys/dev/pci/if_em.h6
-rw-r--r--sys/dev/pci/if_em_hw.c371
-rw-r--r--sys/dev/pci/if_em_hw.h25
-rw-r--r--sys/dev/pci/if_em_osdep.h31
5 files changed, 566 insertions, 49 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index ece1e5bc919..9f043650b2e 100644
--- a/sys/dev/pci/if_em.c
+++ b/sys/dev/pci/if_em.c
@@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
-/* $OpenBSD: if_em.c,v 1.329 2016/01/12 00:05:21 dlg Exp $ */
+/* $OpenBSD: if_em.c,v 1.330 2016/02/18 14:24:39 bluhm Exp $ */
/* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */
#include <dev/pci/if_em.h>
@@ -145,6 +145,10 @@ const struct pci_matchid em_devices[] = {
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I218_V },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I218_V_2 },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I218_V_3 },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM2 },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V2 },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_COPPER },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_FIBER },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_SERDES },
@@ -253,6 +257,9 @@ int em_dma_malloc(struct em_softc *, bus_size_t, struct em_dma_alloc *);
void em_dma_free(struct em_softc *, struct em_dma_alloc *);
u_int32_t em_fill_descriptors(u_int64_t address, u_int32_t length,
PDESC_ARRAY desc_array);
+void em_flush_tx_ring(struct em_softc *);
+void em_flush_rx_ring(struct em_softc *);
+void em_flush_desc_rings(struct em_softc *);
/*********************************************************************
* OpenBSD Device Interface Entry Points
@@ -435,6 +442,7 @@ em_attach(struct device *parent, struct device *self, void *aux)
case em_ich10lan:
case em_pch2lan:
case em_pch_lpt:
+ case em_pch_spt:
case em_80003es2lan:
/* 9K Jumbo Frame size */
sc->hw.max_frame_size = 9234;
@@ -844,6 +852,7 @@ em_init(void *arg)
case em_pchlan:
case em_pch2lan:
case em_pch_lpt:
+ case em_pch_spt:
pba = E1000_PBA_26K;
break;
default:
@@ -1506,10 +1515,12 @@ em_stop(void *arg, int softonly)
timeout_del(&sc->timer_handle);
timeout_del(&sc->tx_fifo_timer_handle);
- if (!softonly) {
+ if (!softonly)
em_disable_intr(sc);
+ if (sc->hw.mac_type == em_pch_spt)
+ em_flush_desc_rings(sc);
+ if (!softonly)
em_reset_hw(&sc->hw);
- }
intr_barrier(sc->sc_intrhand);
ifq_barrier(&ifp->if_snd);
@@ -1563,6 +1574,27 @@ em_identify_hardware(struct em_softc *sc)
sc->hw.phy_init_script = TRUE;
}
+void
+em_legacy_irq_quirk_spt(struct em_softc *sc)
+{
+ uint32_t reg;
+
+ /* Legacy interrupt: SPT needs a quirk. */
+ if (sc->hw.mac_type != em_pch_spt)
+ return;
+ if (sc->legacy_irq == 0)
+ return;
+
+ reg = EM_READ_REG(&sc->hw, E1000_FEXTNVM7);
+ reg |= E1000_FEXTNVM7_SIDE_CLK_UNGATE;
+ EM_WRITE_REG(&sc->hw, E1000_FEXTNVM7, reg);
+
+ reg = EM_READ_REG(&sc->hw, E1000_FEXTNVM9);
+ reg |= E1000_FEXTNVM9_IOSFSB_CLKGATE_DIS |
+ E1000_FEXTNVM9_IOSFSB_CLKREQ_DIS;
+ EM_WRITE_REG(&sc->hw, E1000_FEXTNVM9, reg);
+}
+
int
em_allocate_pci_resources(struct em_softc *sc)
{
@@ -1617,8 +1649,15 @@ em_allocate_pci_resources(struct em_softc *sc)
break;
}
+ sc->osdep.em_flashoffset = 0;
/* for ICH8 and family we need to find the flash memory */
- if (IS_ICH8(sc->hw.mac_type)) {
+ if (sc->hw.mac_type == em_pch_spt) {
+ sc->osdep.flash_bus_space_tag = sc->osdep.mem_bus_space_tag;
+ sc->osdep.flash_bus_space_handle = sc->osdep.mem_bus_space_handle;
+ sc->osdep.em_flashbase = 0;
+ sc->osdep.em_flashsize = 0;
+ sc->osdep.em_flashoffset = 0xe000;
+ } else if (IS_ICH8(sc->hw.mac_type)) {
val = pci_conf_read(pa->pa_pc, pa->pa_tag, EM_FLASH);
if (PCI_MAPREG_TYPE(val) != PCI_MAPREG_TYPE_MEM) {
printf(": flash is not mem space\n");
@@ -1633,9 +1672,13 @@ em_allocate_pci_resources(struct em_softc *sc)
}
}
- if (pci_intr_map_msi(pa, &ih) && pci_intr_map(pa, &ih)) {
- printf(": couldn't map interrupt\n");
- return (ENXIO);
+ sc->legacy_irq = 0;
+ if (pci_intr_map_msi(pa, &ih)) {
+ if (pci_intr_map(pa, &ih)) {
+ printf(": couldn't map interrupt\n");
+ return (ENXIO);
+ }
+ sc->legacy_irq = 1;
}
sc->osdep.dev = (struct device *)sc;
@@ -1717,6 +1760,8 @@ em_hardware_init(struct em_softc *sc)
u_int16_t rx_buffer_size;
INIT_DEBUGOUT("em_hardware_init: begin");
+ if (sc->hw.mac_type == em_pch_spt)
+ em_flush_desc_rings(sc);
/* Issue a global reset */
em_reset_hw(&sc->hw);
@@ -1761,6 +1806,8 @@ em_hardware_init(struct em_softc *sc)
em_write_phy_reg(&sc->hw, IGP02E1000_PHY_POWER_MGMT, phy_tmp);
}
+ em_legacy_irq_quirk_spt(sc);
+
/*
* These parameters control the automatic generation (Tx) and
* response (Rx) to Ethernet PAUSE frames.
@@ -2189,6 +2236,20 @@ em_initialize_transmit_unit(struct em_softc *sc)
reg_tctl |= E1000_HDX_COLLISION_DISTANCE << E1000_COLD_SHIFT;
/* This write will effectively turn on the transmit unit */
E1000_WRITE_REG(&sc->hw, TCTL, reg_tctl);
+
+ /* SPT Si errata workaround to avoid data corruption */
+
+ if (sc->hw.mac_type == em_pch_spt) {
+ uint32_t reg_val;
+
+ reg_val = EM_READ_REG(&sc->hw, E1000_IOSFPC);
+ reg_val |= E1000_RCTL_RDMTS_HEX;
+ EM_WRITE_REG(&sc->hw, E1000_IOSFPC, reg_val);
+
+ reg_val = E1000_READ_REG(&sc->hw, TARC0);
+ reg_val |= E1000_TARC0_CB_MULTIQ_3_REQ;
+ E1000_WRITE_REG(&sc->hw, TARC0, reg_val);
+ }
}
/*********************************************************************
@@ -3068,6 +3129,113 @@ em_disable_aspm(struct em_softc *sc)
offset + PCI_PCIE_LCSR, val);
}
+/*
+ * em_flush_tx_ring - remove all descriptors from the tx_ring
+ *
+ * We want to clear all pending descriptors from the TX ring.
+ * zeroing happens when the HW reads the regs. We assign the ring itself as
+ * the data of the next descriptor. We don't care about the data we are about
+ * to reset the HW.
+ */
+void
+em_flush_tx_ring(struct em_softc *sc)
+{
+ uint32_t tctl, txd_lower = E1000_TXD_CMD_IFCS;
+ uint16_t size = 512;
+ struct em_tx_desc *txd;
+
+ KASSERT(sc->sc_tx_desc_ring != NULL);
+
+ tctl = EM_READ_REG(&sc->hw, E1000_TCTL);
+ EM_WRITE_REG(&sc->hw, E1000_TCTL, tctl | E1000_TCTL_EN);
+
+ KASSERT(EM_READ_REG(&sc->hw, E1000_TDT) == sc->sc_tx_desc_head);
+
+ txd = &sc->sc_tx_desc_ring[sc->sc_tx_desc_head];
+ txd->buffer_addr = sc->sc_tx_dma.dma_map->dm_segs[0].ds_addr;
+ txd->lower.data = htole32(txd_lower | size);
+ txd->upper.data = 0;
+
+ /* flush descriptors to memory before notifying the HW */
+ bus_space_barrier(sc->osdep.mem_bus_space_tag,
+ sc->osdep.mem_bus_space_handle, 0, 0, BUS_SPACE_BARRIER_WRITE);
+
+ if (++sc->sc_tx_desc_head == sc->sc_tx_slots)
+ sc->sc_tx_desc_head = 0;
+
+ EM_WRITE_REG(&sc->hw, E1000_TDT, sc->sc_tx_desc_head);
+ bus_space_barrier(sc->osdep.mem_bus_space_tag, sc->osdep.mem_bus_space_handle,
+ 0, 0, BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
+ usec_delay(250);
+}
+
+/*
+ * em_flush_rx_ring - remove all descriptors from the rx_ring
+ *
+ * Mark all descriptors in the RX ring as consumed and disable the rx ring
+ */
+void
+em_flush_rx_ring(struct em_softc *sc)
+{
+ uint32_t rctl, rxdctl;
+
+ rctl = EM_READ_REG(&sc->hw, E1000_RCTL);
+ EM_WRITE_REG(&sc->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
+ E1000_WRITE_FLUSH(&sc->hw);
+ usec_delay(150);
+
+ rxdctl = EM_READ_REG(&sc->hw, E1000_RXDCTL);
+ /* zero the lower 14 bits (prefetch and host thresholds) */
+ rxdctl &= 0xffffc000;
+ /*
+ * update thresholds: prefetch threshold to 31, host threshold to 1
+ * and make sure the granularity is "descriptors" and not "cache lines"
+ */
+ rxdctl |= (0x1F | (1 << 8) | E1000_RXDCTL_THRESH_UNIT_DESC);
+ EM_WRITE_REG(&sc->hw, E1000_RXDCTL, rxdctl);
+
+ /* momentarily enable the RX ring for the changes to take effect */
+ EM_WRITE_REG(&sc->hw, E1000_RCTL, rctl | E1000_RCTL_EN);
+ E1000_WRITE_FLUSH(&sc->hw);
+ usec_delay(150);
+ EM_WRITE_REG(&sc->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
+}
+
+/*
+ * em_flush_desc_rings - remove all descriptors from the descriptor rings
+ *
+ * In i219, the descriptor rings must be emptied before resetting the HW
+ * or before changing the device state to D3 during runtime (runtime PM).
+ *
+ * Failure to do this will cause the HW to enter a unit hang state which can
+ * only be released by PCI reset on the device
+ *
+ */
+void
+em_flush_desc_rings(struct em_softc *sc)
+{
+ struct pci_attach_args *pa = &sc->osdep.em_pa;
+ uint32_t fextnvm11, tdlen;
+ uint16_t hang_state;
+
+ /* First, disable MULR fix in FEXTNVM11 */
+ fextnvm11 = EM_READ_REG(&sc->hw, E1000_FEXTNVM11);
+ fextnvm11 |= E1000_FEXTNVM11_DISABLE_MULR_FIX;
+ EM_WRITE_REG(&sc->hw, E1000_FEXTNVM11, fextnvm11);
+
+ /* do nothing if we're not in faulty state, or if the queue is empty */
+ tdlen = EM_READ_REG(&sc->hw, E1000_TDLEN);
+ hang_state = pci_conf_read(pa->pa_pc, pa->pa_tag, PCICFG_DESC_RING_STATUS);
+ if (!(hang_state & FLUSH_DESC_REQUIRED) || !tdlen)
+ return;
+ em_flush_tx_ring(sc);
+
+ /* recheck, maybe the fault is caused by the rx ring */
+ hang_state = pci_conf_read(pa->pa_pc, pa->pa_tag, PCICFG_DESC_RING_STATUS);
+ if (hang_state & FLUSH_DESC_REQUIRED)
+ em_flush_rx_ring(sc);
+}
+
#ifndef SMALL_KERNEL
/**********************************************************************
*
diff --git a/sys/dev/pci/if_em.h b/sys/dev/pci/if_em.h
index 84fe5b1814c..cf71c713287 100644
--- a/sys/dev/pci/if_em.h
+++ b/sys/dev/pci/if_em.h
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
/* $FreeBSD: if_em.h,v 1.26 2004/09/01 23:22:41 pdeuskar Exp $ */
-/* $OpenBSD: if_em.h,v 1.71 2016/01/11 01:31:53 dlg Exp $ */
+/* $OpenBSD: if_em.h,v 1.72 2016/02/18 14:24:39 bluhm Exp $ */
#ifndef _EM_H_DEFINED_
#define _EM_H_DEFINED_
@@ -230,6 +230,9 @@ typedef int boolean_t;
#define MAX_NUM_MULTICAST_ADDRESSES 128
+#define PCICFG_DESC_RING_STATUS 0xe4
+#define FLUSH_DESC_REQUIRED 0x100
+
/*
* TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
* multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will
@@ -319,6 +322,7 @@ struct em_softc {
struct em_osdep osdep;
struct ifmedia media;
int io_rid;
+ int legacy_irq;
void *sc_intrhand;
struct timeout em_intr_enable;
diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c
index 06daed28c17..a006db3daa3 100644
--- a/sys/dev/pci/if_em_hw.c
+++ b/sys/dev/pci/if_em_hw.c
@@ -31,7 +31,7 @@
*******************************************************************************/
-/* $OpenBSD: if_em_hw.c,v 1.90 2015/12/14 03:04:10 mmcc Exp $ */
+/* $OpenBSD: if_em_hw.c,v 1.91 2016/02/18 14:24:39 bluhm Exp $ */
/*
* if_em_hw.c Shared functions for accessing and configuring the MAC
*/
@@ -106,6 +106,7 @@ static int32_t em_read_ich8_byte(struct em_hw *, uint32_t, uint8_t *);
static int32_t em_verify_write_ich8_byte(struct em_hw *, uint32_t, uint8_t);
static int32_t em_write_ich8_byte(struct em_hw *, uint32_t, uint8_t);
static int32_t em_read_ich8_word(struct em_hw *, uint32_t, uint16_t *);
+static int32_t em_read_ich8_dword(struct em_hw *, uint32_t, uint32_t *);
static int32_t em_read_ich8_data(struct em_hw *, uint32_t, uint32_t,
uint16_t *);
static int32_t em_write_ich8_data(struct em_hw *, uint32_t, uint32_t,
@@ -610,6 +611,12 @@ em_set_mac_type(struct em_hw *hw)
case E1000_DEV_ID_PCH_I218_V3:
hw->mac_type = em_pch_lpt;
break;
+ case E1000_DEV_ID_PCH_SPT_I219_LM:
+ case E1000_DEV_ID_PCH_SPT_I219_V:
+ case E1000_DEV_ID_PCH_SPT_I219_LM2:
+ case E1000_DEV_ID_PCH_SPT_I219_V2:
+ hw->mac_type = em_pch_spt;
+ break;
case E1000_DEV_ID_EP80579_LAN_1:
hw->mac_type = em_icp_xxxx;
hw->icp_xxxx_port_num = 0;
@@ -640,6 +647,7 @@ em_set_mac_type(struct em_hw *hw)
case em_pchlan:
case em_pch2lan:
case em_pch_lpt:
+ case em_pch_spt:
hw->swfwhw_semaphore_present = TRUE;
hw->asf_firmware_present = TRUE;
break;
@@ -736,6 +744,7 @@ em_set_media_type(struct em_hw *hw)
case em_pchlan:
case em_pch2lan:
case em_pch_lpt:
+ case em_pch_spt:
case em_82573:
case em_82574:
/*
@@ -893,6 +902,7 @@ em_reset_hw(struct em_hw *hw)
case em_pchlan:
case em_pch2lan:
case em_pch_lpt:
+ case em_pch_spt:
if (!hw->phy_reset_disable &&
em_check_phy_reset_block(hw) == E1000_SUCCESS) {
/*
@@ -1141,6 +1151,7 @@ em_initialize_hardware_bits(struct em_hw *hw)
case em_pchlan:
case em_pch2lan:
case em_pch_lpt:
+ case em_pch_spt:
if (hw->mac_type == em_ich8lan)
/* Set TARC0 bits 29 and 28 */
reg_tarc0 |= 0x30000000;
@@ -1215,7 +1226,8 @@ em_init_hw(struct em_hw *hw)
if (hw->mac_type == em_pchlan ||
hw->mac_type == em_pch2lan ||
- hw->mac_type == em_pch_lpt) {
+ hw->mac_type == em_pch_lpt ||
+ hw->mac_type == em_pch_spt) {
/*
* The MAC-PHY interconnect may still be in SMBus mode
* after Sx->S0. Toggle the LANPHYPC Value bit to force
@@ -1426,6 +1438,7 @@ em_init_hw(struct em_hw *hw)
case em_pchlan:
case em_pch2lan:
case em_pch_lpt:
+ case em_pch_spt:
ctrl = E1000_READ_REG(hw, TXDCTL1);
ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB;
@@ -1557,6 +1570,7 @@ em_setup_link(struct em_hw *hw)
case em_pchlan:
case em_pch2lan:
case em_pch_lpt:
+ case em_pch_spt:
case em_82573:
case em_82574:
hw->fc = E1000_FC_FULL;
@@ -2007,7 +2021,8 @@ em_copper_link_igp_setup(struct em_hw *hw)
/* disable lplu d0 during driver init */
if (hw->mac_type == em_pchlan ||
hw->mac_type == em_pch2lan ||
- hw->mac_type == em_pch_lpt)
+ hw->mac_type == em_pch_lpt ||
+ hw->mac_type == em_pch_spt)
ret_val = em_set_lplu_state_pchlan(hw, FALSE);
else
ret_val = em_set_d0_lplu_state(hw, FALSE);
@@ -2279,7 +2294,8 @@ em_copper_link_mgp_setup(struct em_hw *hw)
/* disable lplu d0 during driver init */
if (hw->mac_type == em_pchlan ||
hw->mac_type == em_pch2lan ||
- hw->mac_type == em_pch_lpt)
+ hw->mac_type == em_pch_lpt ||
+ hw->mac_type == em_pch_spt)
ret_val = em_set_lplu_state_pchlan(hw, FALSE);
/* Enable CRS on TX. This must be set for half-duplex operation. */
@@ -2750,6 +2766,7 @@ em_setup_copper_link(struct em_hw *hw)
case em_pchlan:
case em_pch2lan:
case em_pch_lpt:
+ case em_pch_spt:
/*
* Set the mac to wait the maximum time between each
* iteration and increase the max iterations when polling the
@@ -3917,7 +3934,8 @@ em_check_for_link(struct em_hw *hw)
/* Enable/Disable EEE after link up */
if (hw->mac_type == em_pch2lan ||
- hw->mac_type == em_pch_lpt) {
+ hw->mac_type == em_pch_lpt ||
+ hw->mac_type == em_pch_spt) {
ret_val = em_set_eee_pchlan(hw);
if (ret_val)
return ret_val;
@@ -4702,7 +4720,8 @@ em_read_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t *phy_data)
if (hw->mac_type == em_pchlan ||
hw->mac_type == em_pch2lan ||
- hw->mac_type == em_pch_lpt)
+ hw->mac_type == em_pch_lpt ||
+ hw->mac_type == em_pch_spt)
return (em_access_phy_reg_hv(hw, reg_addr, phy_data, TRUE));
if (((hw->mac_type == em_80003es2lan) || (hw->mac_type == em_82575)) &&
@@ -4815,7 +4834,7 @@ em_read_phy_reg_ex(struct em_hw *hw, uint32_t reg_addr, uint16_t *phy_data)
}
*phy_data = (uint16_t) mdic;
- if (hw->mac_type == em_pch2lan || hw->mac_type == em_pch_lpt)
+ if (hw->mac_type == em_pch2lan || hw->mac_type == em_pch_lpt || hw->mac_type == em_pch_spt)
usec_delay(100);
} else {
/*
@@ -4866,7 +4885,8 @@ em_write_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t phy_data)
if (hw->mac_type == em_pchlan ||
hw->mac_type == em_pch2lan ||
- hw->mac_type == em_pch_lpt)
+ hw->mac_type == em_pch_lpt ||
+ hw->mac_type == em_pch_spt)
return (em_access_phy_reg_hv(hw, reg_addr, &phy_data, FALSE));
if (em_swfw_sync_acquire(hw, hw->swfw))
@@ -4966,7 +4986,7 @@ em_write_phy_reg_ex(struct em_hw *hw, uint32_t reg_addr, uint16_t phy_data)
return -E1000_ERR_PHY;
}
- if (hw->mac_type == em_pch2lan || hw->mac_type == em_pch_lpt)
+ if (hw->mac_type == em_pch2lan || hw->mac_type == em_pch_lpt || hw->mac_type == em_pch_spt)
usec_delay(100);
} else {
/*
@@ -5455,6 +5475,7 @@ em_match_gig_phy(struct em_hw *hw)
match = TRUE;
break;
case em_pch_lpt:
+ case em_pch_spt:
if (hw->phy_id == I217_E_PHY_ID)
match = TRUE;
break;
@@ -5783,6 +5804,33 @@ em_init_eeprom_params(struct em_hw *hw)
break;
}
+ case em_pch_spt:
+ {
+ int32_t i = 0;
+ uint32_t flash_size = EM_READ_REG(hw, 0xc /* STRAP */);
+
+ eeprom->type = em_eeprom_ich8;
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
+ eeprom->word_size = E1000_SHADOW_RAM_WORDS;
+ /*
+ * Zero the shadow RAM structure. But don't load it
+ * from NVM so as to save time for driver init
+ */
+ if (hw->eeprom_shadow_ram != NULL) {
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+ hw->eeprom_shadow_ram[i].modified =
+ FALSE;
+ hw->eeprom_shadow_ram[i].eeprom_word =
+ 0xFFFF;
+ }
+ }
+ hw->flash_base_addr = 0;
+ flash_size = ((flash_size >> 1) & 0x1f) + 1;
+ flash_size *= 4096;
+ hw->flash_bank_size = flash_size / 4;
+ }
+ break;
default:
break;
}
@@ -6470,6 +6518,7 @@ em_validate_eeprom_checksum(struct em_hw *hw)
*/
switch (hw->mac_type) {
case em_pch_lpt:
+ case em_pch_spt:
word = EEPROM_COMPAT;
valid_csum_mask = EEPROM_COMPAT_VALID_CSUM;
break;
@@ -7131,7 +7180,7 @@ em_init_rx_addrs(struct em_hw *hw)
uint32_t rar_num;
DEBUGFUNC("em_init_rx_addrs");
- if (hw->mac_type == em_pch_lpt || hw->mac_type == em_pch2lan)
+ if (hw->mac_type == em_pch_lpt || hw->mac_type == em_pch_spt || hw->mac_type == em_pch2lan)
if (em_phy_no_cable_workaround(hw))
printf(" ...failed to apply em_phy_no_cable_"
"workaround.\n");
@@ -7688,7 +7737,7 @@ em_clear_hw_cntrs(struct em_hw *hw)
hw->mac_type == em_ich9lan ||
hw->mac_type == em_ich10lan ||
hw->mac_type == em_pchlan ||
- (hw->mac_type != em_pch2lan && hw->mac_type != em_pch_lpt))
+ (hw->mac_type != em_pch2lan && hw->mac_type != em_pch_lpt && hw->mac_type != em_pch_spt))
return;
temp = E1000_READ_REG(hw, ICRXPTC);
@@ -7830,6 +7879,7 @@ em_get_bus_info(struct em_hw *hw)
case em_pchlan:
case em_pch2lan:
case em_pch_lpt:
+ case em_pch_spt:
hw->bus_type = em_bus_type_pci_express;
hw->bus_speed = em_bus_speed_2500;
hw->bus_width = em_bus_width_pciex_1;
@@ -9022,6 +9072,7 @@ em_get_auto_rd_done(struct em_hw *hw)
case em_pchlan:
case em_pch2lan:
case em_pch_lpt:
+ case em_pch_spt:
while (timeout) {
if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD)
break;
@@ -9380,12 +9431,45 @@ em_valid_nvm_bank_detect_ich8lan(struct em_hw *hw, uint32_t *bank)
uint32_t eecd;
uint32_t bank1_offset = hw->flash_bank_size * sizeof(uint16_t);
uint32_t act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
+ uint32_t nvm_dword = 0;
uint8_t sig_byte = 0;
int32_t ret_val;
DEBUGFUNC("em_valid_nvm_bank_detect_ich8lan");
switch (hw->mac_type) {
+ case em_pch_spt:
+ bank1_offset = hw->flash_bank_size * 2;
+ act_offset = E1000_ICH_NVM_SIG_WORD * 2;
+
+ /* set bank to 0 in case flash read fails. */
+ *bank = 0;
+
+ /* Check bank 0 */
+ ret_val = em_read_ich8_dword(hw, act_offset, &nvm_dword);
+ if (ret_val)
+ return ret_val;
+ sig_byte = (uint8_t)((nvm_dword & 0xFF00) >> 8);
+ if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+ E1000_ICH_NVM_SIG_VALUE) {
+ *bank = 0;
+ return 0;
+ }
+
+ /* Check bank 1 */
+ ret_val = em_read_ich8_dword(hw, act_offset + bank1_offset,
+ &nvm_dword);
+ if (ret_val)
+ return ret_val;
+ sig_byte = (uint8_t)((nvm_dword & 0xFF00) >> 8);
+ if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+ E1000_ICH_NVM_SIG_VALUE) {
+ *bank = 1;
+ return 0;
+ }
+
+ DEBUGOUT("ERROR: No valid NVM bank present\n");
+ return -1;
case em_ich8lan:
case em_ich9lan:
eecd = E1000_READ_REG(hw, EECD);
@@ -9432,6 +9516,92 @@ em_valid_nvm_bank_detect_ich8lan(struct em_hw *hw, uint32_t *bank)
}
}
+STATIC int32_t
+em_read_eeprom_spt(struct em_hw *hw, uint16_t offset, uint16_t words,
+ uint16_t *data)
+{
+ int32_t error = E1000_SUCCESS;
+ uint32_t flash_bank = 0;
+ uint32_t act_offset = 0;
+ uint32_t bank_offset = 0;
+ uint32_t dword = 0;
+ uint16_t i = 0, add;
+
+ /*
+ * We need to know which is the valid flash bank. In the event that
+ * we didn't allocate eeprom_shadow_ram, we may not be managing
+ * flash_bank. So it cannot be trusted and needs to be updated with
+ * each read.
+ */
+
+ if (hw->mac_type != em_pch_spt)
+ return -E1000_ERR_EEPROM;
+
+ error = em_get_software_flag(hw);
+ if (error != E1000_SUCCESS)
+ return error;
+
+ error = em_valid_nvm_bank_detect_ich8lan(hw, &flash_bank);
+ if (error != E1000_SUCCESS) {
+ DEBUGOUT("Could not detect valid bank, assuming bank 0\n");
+ flash_bank = 0;
+ }
+
+ /*
+ * Adjust offset appropriately if we're on bank 1 - adjust for word
+ * size
+ */
+ bank_offset = flash_bank * (hw->flash_bank_size * 2);
+
+ for (i = add = 0; i < words; i += add) {
+ if ((offset + i) % 2) {
+ add = 1;
+ if (hw->eeprom_shadow_ram != NULL
+ && hw->eeprom_shadow_ram[offset + i].modified) {
+ data[i] =
+ hw->eeprom_shadow_ram[offset+i].eeprom_word;
+ continue;
+ }
+ act_offset = bank_offset + (offset + i - 1) * 2;
+ } else {
+ add = 2;
+ if (hw->eeprom_shadow_ram != NULL
+ && hw->eeprom_shadow_ram[offset+i].modified
+ && hw->eeprom_shadow_ram[offset+i+1].modified) {
+ data[i] = hw->eeprom_shadow_ram[offset+i].eeprom_word;
+ data[i+1] = hw->eeprom_shadow_ram[offset+i+1].eeprom_word;
+ continue;
+ }
+ act_offset = bank_offset + (offset + i) * 2;
+ }
+ error = em_read_ich8_dword(hw, act_offset, &dword);
+ if (error != E1000_SUCCESS)
+ break;
+ if (hw->eeprom_shadow_ram != NULL
+ && hw->eeprom_shadow_ram[offset+i].modified) {
+ data[i] = hw->eeprom_shadow_ram[offset+i].eeprom_word;
+ } else {
+ if (add == 1)
+ data[i] = dword >> 16;
+ else
+ data[i] = dword & 0xFFFFUL;
+ }
+ if (add == 1 || words-i == 1)
+ continue;
+ if (hw->eeprom_shadow_ram != NULL
+ && hw->eeprom_shadow_ram[offset+i+1].modified) {
+ data[i+1] =
+ hw->eeprom_shadow_ram[offset+i+1].eeprom_word;
+ } else {
+ data[i+1] = dword >> 16;
+ }
+ }
+
+ em_release_software_flag(hw);
+
+ return error;
+}
+
/******************************************************************************
* Reads a 16 bit word or words from the EEPROM using the ICH8's flash access
* register.
@@ -9458,6 +9628,9 @@ em_read_eeprom_ich8(struct em_hw *hw, uint16_t offset, uint16_t words,
* each read.
*/
+ if (hw->mac_type == em_pch_spt)
+ return em_read_eeprom_spt(hw, offset, words, data);
+
error = em_get_software_flag(hw);
if (error != E1000_SUCCESS)
return error;
@@ -9562,7 +9735,12 @@ em_ich8_cycle_init(struct em_hw *hw)
int32_t i = 0;
DEBUGFUNC("em_ich8_cycle_init");
- hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
+ if (hw->mac_type == em_pch_spt)
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG32(hw,
+ ICH_FLASH_HSFSTS) & 0xFFFFUL;
+ else
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw,
+ ICH_FLASH_HSFSTS);
/* May be check the Flash Des Valid bit in Hw status */
if (hsfsts.hsf_status.fldesvalid == 0) {
@@ -9574,8 +9752,12 @@ em_ich8_cycle_init(struct em_hw *hw)
/* Clear DAEL in Hw status by writing a 1 */
hsfsts.hsf_status.flcerr = 1;
hsfsts.hsf_status.dael = 1;
-
- E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
+ if (hw->mac_type == em_pch_spt)
+ E1000_WRITE_ICH_FLASH_REG32(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval & 0xFFFFUL);
+ else
+ E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval);
/*
* Either we should have a hardware SPI cycle in progress bit to
* check against, in order to start a new cycle or FDONE bit should
@@ -9595,8 +9777,12 @@ em_ich8_cycle_init(struct em_hw *hw)
*/
/* Begin by setting Flash Cycle Done. */
hsfsts.hsf_status.flcdone = 1;
- E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
- hsfsts.regval);
+ if (hw->mac_type == em_pch_spt)
+ E1000_WRITE_ICH_FLASH_REG32(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval & 0xFFFFUL);
+ else
+ E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval);
error = E1000_SUCCESS;
} else {
/*
@@ -9604,8 +9790,12 @@ em_ich8_cycle_init(struct em_hw *hw)
* chance to end before giving up.
*/
for (i = 0; i < ICH_FLASH_COMMAND_TIMEOUT; i++) {
- hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw,
- ICH_FLASH_HSFSTS);
+ if (hw->mac_type == em_pch_spt)
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG32(
+ hw, ICH_FLASH_HSFSTS) & 0xFFFFUL;
+ else
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(
+ hw, ICH_FLASH_HSFSTS);
if (hsfsts.hsf_status.flcinprog == 0) {
error = E1000_SUCCESS;
break;
@@ -9618,8 +9808,12 @@ em_ich8_cycle_init(struct em_hw *hw)
* timeout, now set the Flash Cycle Done.
*/
hsfsts.hsf_status.flcdone = 1;
- E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
- hsfsts.regval);
+ if (hw->mac_type == em_pch_spt)
+ E1000_WRITE_ICH_FLASH_REG32(hw,
+ ICH_FLASH_HSFSTS, hsfsts.regval & 0xFFFFUL);
+ else
+ E1000_WRITE_ICH_FLASH_REG16(hw,
+ ICH_FLASH_HSFSTS, hsfsts.regval);
} else {
DEBUGOUT("Flash controller busy, cannot get access");
}
@@ -9639,15 +9833,31 @@ em_ich8_flash_cycle(struct em_hw *hw, uint32_t timeout)
union ich8_hws_flash_status hsfsts;
int32_t error = E1000_ERR_EEPROM;
uint32_t i = 0;
+
/* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
- hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+ if (hw->mac_type == em_pch_spt)
+ hsflctl.regval = E1000_READ_ICH_FLASH_REG32(hw,
+ ICH_FLASH_HSFSTS) >> 16;
+ else
+ hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw,
+ ICH_FLASH_HSFCTL);
hsflctl.hsf_ctrl.flcgo = 1;
- E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
+
+ if (hw->mac_type == em_pch_spt)
+ E1000_WRITE_ICH_FLASH_REG32(hw, ICH_FLASH_HSFSTS,
+ (uint32_t)hsflctl.regval << 16);
+ else
+ E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
+ hsflctl.regval);
/* wait till FDONE bit is set to 1 */
do {
- hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw,
- ICH_FLASH_HSFSTS);
+ if (hw->mac_type == em_pch_spt)
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG32(hw,
+ ICH_FLASH_HSFSTS) & 0xFFFFUL;
+ else
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw,
+ ICH_FLASH_HSFSTS);
if (hsfsts.hsf_status.flcdone == 1)
break;
usec_delay(1);
@@ -9706,7 +9916,7 @@ em_read_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size,
*/
/* TODO: TBD maybe check the index against the size of flash */
- E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR,
+ E1000_WRITE_ICH_FLASH_REG32(hw, ICH_FLASH_FADDR,
flash_linear_address);
error = em_ich8_flash_cycle(hw, ICH_FLASH_COMMAND_TIMEOUT);
@@ -9748,11 +9958,88 @@ em_read_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size,
return error;
}
+STATIC int32_t
+em_read_ich8_data32(struct em_hw *hw, uint32_t offset, uint32_t *data)
+{
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+ uint32_t flash_linear_address;
+ int32_t error = -E1000_ERR_EEPROM;
+ uint32_t count = 0;
+ DEBUGFUNC("em_read_ich8_data32");
+
+ if (hw->mac_type != em_pch_spt)
+ return error;
+ if (offset > ICH_FLASH_LINEAR_ADDR_MASK)
+ return error;
+ flash_linear_address = (ICH_FLASH_LINEAR_ADDR_MASK & offset) +
+ hw->flash_base_addr;
+
+ do {
+ usec_delay(1);
+ /* Steps */
+ error = em_ich8_cycle_init(hw);
+ if (error != E1000_SUCCESS)
+ break;
+
+ /* 32 bit accesses in SPT. */
+ hsflctl.regval = E1000_READ_ICH_FLASH_REG32(hw,
+ ICH_FLASH_HSFSTS) >> 16;
+
+ hsflctl.hsf_ctrl.fldbcount = sizeof(uint32_t) - 1;
+ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
+
+ E1000_WRITE_ICH_FLASH_REG32(hw, ICH_FLASH_HSFSTS,
+ (uint32_t)hsflctl.regval << 16);
+ /*
+ * Write the last 24 bits of offset into Flash Linear address
+ * field in Flash Address
+ */
+ /* TODO: TBD maybe check the offset against the size of flash */
+
+ E1000_WRITE_ICH_FLASH_REG32(hw, ICH_FLASH_FADDR,
+ flash_linear_address);
+
+ error = em_ich8_flash_cycle(hw, ICH_FLASH_COMMAND_TIMEOUT);
+ /*
+ * Check if FCERR is set to 1, if set to 1, clear it and try
+ * the whole sequence a few more times, else read in (shift
+ * in) the Flash Data0, the order is least significant byte
+ * first msb to lsb
+ */
+ if (error == E1000_SUCCESS) {
+ (*data) = (uint32_t)E1000_READ_ICH_FLASH_REG32(hw,
+ ICH_FLASH_FDATA0);
+ break;
+ } else {
+ /*
+ * If we've gotten here, then things are probably
+ * completely hosed, but if the error condition is
+ * detected, it won't hurt to give it another
+ * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
+ */
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw,
+ ICH_FLASH_HSFSTS);
+ if (hsfsts.hsf_status.flcerr == 1) {
+ /* Repeat for some time before giving up. */
+ continue;
+ } else if (hsfsts.hsf_status.flcdone == 0) {
+ DEBUGOUT("Timeout error - flash cycle did not"
+ " complete.");
+ break;
+ }
+ }
+ } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
+
+ return error;
+}
+
+
/******************************************************************************
* Writes One /two bytes to the NVM using the ICH8 flash access registers.
*
* hw - The pointer to the hw structure
- * index - The index of the byte/word to read.
+ * index - The index of the byte/word to write.
* size - Size of data to read, 1=byte 2=word
* data - The byte(s) to write to the NVM.
*****************************************************************************/
@@ -9768,6 +10055,8 @@ em_write_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size,
int32_t count = 0;
DEBUGFUNC("em_write_ich8_data");
+ if (hw->mac_type == em_pch_spt)
+ return -E1000_ERR_EEPROM;
if (size < 1 || size > 2 || data > size * 0xff ||
index > ICH_FLASH_LINEAR_ADDR_MASK)
return error;
@@ -9793,7 +10082,7 @@ em_write_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size,
* Write the last 24 bits of index into Flash Linear address
* field in Flash Address
*/
- E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR,
+ E1000_WRITE_ICH_FLASH_REG32(hw, ICH_FLASH_FADDR,
flash_linear_address);
if (size == 1)
@@ -9801,7 +10090,7 @@ em_write_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size,
else
flash_data = (uint32_t) data;
- E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data);
+ E1000_WRITE_ICH_FLASH_REG32(hw, ICH_FLASH_FDATA0, flash_data);
/*
* check if FCERR is set to 1 , if set to 1, clear it and try
* the whole sequence a few more times else done
@@ -9844,7 +10133,11 @@ em_read_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t *data)
{
int32_t status = E1000_SUCCESS;
uint16_t word = 0;
- status = em_read_ich8_data(hw, index, 1, &word);
+
+ if (hw->mac_type == em_pch_spt)
+ return -E1000_ERR_EEPROM;
+ else
+ status = em_read_ich8_data(hw, index, 1, &word);
if (status == E1000_SUCCESS) {
*data = (uint8_t) word;
}
@@ -9904,6 +10197,21 @@ em_write_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t data)
}
/******************************************************************************
+ * Reads a dword from the NVM using the ICH8 flash access registers.
+ *
+ * hw - pointer to em_hw structure
+ * index - The starting BYTE index of the word to read.
+ * data - Pointer to a word to store the value read.
+ *****************************************************************************/
+STATIC int32_t
+em_read_ich8_dword(struct em_hw *hw, uint32_t index, uint32_t *data)
+{
+ int32_t status = E1000_SUCCESS;
+ status = em_read_ich8_data32(hw, index, data);
+ return status;
+}
+
+/******************************************************************************
* Reads a word from the NVM using the ICH8 flash access registers.
*
* hw - pointer to em_hw structure
@@ -10030,7 +10338,7 @@ em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t bank)
flash_linear_address += hw->flash_base_addr;
flash_linear_address &= ICH_FLASH_LINEAR_ADDR_MASK;
- E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR,
+ E1000_WRITE_ICH_FLASH_REG32(hw, ICH_FLASH_FADDR,
flash_linear_address);
error =
@@ -10230,7 +10538,8 @@ em_init_lcd_from_nvm(struct em_hw *hw)
hw->device_id == E1000_DEV_ID_ICH8_IGP_M ||
hw->mac_type == em_pchlan ||
hw->mac_type == em_pch2lan ||
- hw->mac_type == em_pch_lpt)
+ hw->mac_type == em_pch_lpt ||
+ hw->mac_type == em_pch_spt)
sw_cfg_mask = FEXTNVM_SW_CONFIG_ICH8M;
else
sw_cfg_mask = FEXTNVM_SW_CONFIG;
diff --git a/sys/dev/pci/if_em_hw.h b/sys/dev/pci/if_em_hw.h
index a44a37ac8cd..8e5cc529e7f 100644
--- a/sys/dev/pci/if_em_hw.h
+++ b/sys/dev/pci/if_em_hw.h
@@ -31,7 +31,7 @@
*******************************************************************************/
-/* $OpenBSD: if_em_hw.h,v 1.67 2015/09/12 02:38:14 jsg Exp $ */
+/* $OpenBSD: if_em_hw.h,v 1.68 2016/02/18 14:24:39 bluhm Exp $ */
/* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */
/* if_em_hw.h
@@ -80,12 +80,13 @@ typedef enum {
em_pchlan,
em_pch2lan,
em_pch_lpt,
+ em_pch_spt,
em_num_macs
} em_mac_type;
#define IS_ICH8(t) \
(t == em_ich8lan || t == em_ich9lan || t == em_ich10lan || \
- t == em_pchlan || t == em_pch2lan || t == em_pch_lpt)
+ t == em_pchlan || t == em_pch2lan || t == em_pch_lpt || t == em_pch_spt)
typedef enum {
em_eeprom_uninitialized = 0,
@@ -554,6 +555,10 @@ int32_t em_check_phy_reset_block(struct em_hw *hw);
#define E1000_DEV_ID_PCH_I218_V2 0x15A1
#define E1000_DEV_ID_PCH_I218_LM3 0x15A2
#define E1000_DEV_ID_PCH_I218_V3 0x15A3
+#define E1000_DEV_ID_PCH_SPT_I219_LM 0x156F
+#define E1000_DEV_ID_PCH_SPT_I219_V 0x1570
+#define E1000_DEV_ID_PCH_SPT_I219_LM2 0x15B7
+#define E1000_DEV_ID_PCH_SPT_I219_V2 0x15B8
#define E1000_DEV_ID_82575EB_PT 0x10A7
#define E1000_DEV_ID_82575EB_PF 0x10A9
#define E1000_DEV_ID_82575GB_QP 0x10D6
@@ -1030,6 +1035,7 @@ struct em_ffvt_entry {
#define FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M :/ */
#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
#define E1000_PBS 0x01008 /* Packet Buffer Size */
+#define E1000_IOSFPC 0x00F28 /* TX corrupted data */
#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
#define E1000_FLASH_UPDATES 1000
#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
@@ -2044,6 +2050,7 @@ struct em_hw {
#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */
#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */
#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */
+#define E1000_RCTL_RDMTS_HEX 0x00010000
#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */
#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */
@@ -2145,7 +2152,7 @@ struct em_hw {
#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */
#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */
#define E1000_RXDCTL_WTHRESH 0x003F0000 /* RXDCTL Writeback Threshold */
-#define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */
+#define E1000_RXDCTL_THRESH_UNIT_DESC 0x1000000
#define E1000_RXDCTL_QUEUE_ENABLE 0x2000000
/* Transmit Descriptor Control */
@@ -2259,6 +2266,9 @@ struct em_hw {
#define E1000_WUS_FLX3 0x00080000 /* Flexible Filter 3 Match */
#define E1000_WUS_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
+/* TRAC0 bits */
+#define E1000_TARC0_CB_MULTIQ_3_REQ (1 << 28 | 1 << 29)
+
/* Management Control */
#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */
#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */
@@ -3729,6 +3739,15 @@ union ich8_hws_flash_regacc {
#define I2_MODE_CTRL HV_KMRN_MODE_CTRL
#define I2_PCIE_POWER_CTRL IGP3_KMRN_POWER_MNG_CTRL
+/* FEXTNVM registers */
+#define E1000_FEXTNVM7 0xe4UL
+#define E1000_FEXTNVM7_SIDE_CLK_UNGATE 0x04UL
+#define E1000_FEXTNVM9 0x5bb4UL
+#define E1000_FEXTNVM9_IOSFSB_CLKGATE_DIS 0x0800UL
+#define E1000_FEXTNVM9_IOSFSB_CLKREQ_DIS 0x1000UL
+#define E1000_FEXTNVM11 0x05bbc
+#define E1000_FEXTNVM11_DISABLE_MULR_FIX 0x00002000
+
/* BM/HV Specific Registers */
#define BM_PORT_CTRL_PAGE 769
#define BM_PCIE_PAGE 770
diff --git a/sys/dev/pci/if_em_osdep.h b/sys/dev/pci/if_em_osdep.h
index bec2f2d5ed8..be52bc92f45 100644
--- a/sys/dev/pci/if_em_osdep.h
+++ b/sys/dev/pci/if_em_osdep.h
@@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
-/* $OpenBSD: if_em_osdep.h,v 1.12 2011/10/05 02:52:10 jsg Exp $ */
+/* $OpenBSD: if_em_osdep.h,v 1.13 2016/02/18 14:24:39 bluhm Exp $ */
/* $FreeBSD: if_em_osdep.h,v 1.11 2003/05/02 21:17:08 pdeuskar Exp $ */
#ifndef _EM_OPENBSD_OS_H_
@@ -78,6 +78,7 @@ struct em_osdep
bus_addr_t em_iobase;
bus_size_t em_flashsize;
bus_addr_t em_flashbase;
+ size_t em_flashoffset;
};
#define E1000_WRITE_FLUSH(hw) E1000_READ_REG(hw, STATUS)
@@ -151,21 +152,37 @@ struct em_osdep
#define E1000_READ_ICH_FLASH_REG(hw, reg) \
bus_space_read_4(((struct em_osdep *)(hw)->back)->flash_bus_space_tag, \
- ((struct em_osdep *)(hw)->back)->flash_bus_space_handle, reg)
+ ((struct em_osdep *)(hw)->back)->flash_bus_space_handle, \
+ ((struct em_osdep *)(hw)->back)->em_flashoffset + reg)
#define E1000_READ_ICH_FLASH_REG16(hw, reg) \
bus_space_read_2(((struct em_osdep *)(hw)->back)->flash_bus_space_tag, \
- ((struct em_osdep *)(hw)->back)->flash_bus_space_handle, reg)
+ ((struct em_osdep *)(hw)->back)->flash_bus_space_handle, \
+ ((struct em_osdep *)(hw)->back)->em_flashoffset + reg)
-#define E1000_WRITE_ICH_FLASH_REG(hw, reg, value) \
- bus_space_write_4(((struct em_osdep *)(hw)->back)->flash_bus_space_tag, \
+#define E1000_READ_ICH_FLASH_REG32(hw, reg) \
+ bus_space_read_4(((struct em_osdep *)(hw)->back)->flash_bus_space_tag, \
+ ((struct em_osdep *)(hw)->back)->flash_bus_space_handle, \
+ ((struct em_osdep *)(hw)->back)->em_flashoffset + reg)
+
+
+#define E1000_WRITE_ICH_FLASH_REG8(hw, reg, value) \
+ bus_space_write_1(((struct em_osdep *)(hw)->back)->flash_bus_space_tag, \
((struct em_osdep *)(hw)->back)->flash_bus_space_handle, \
- reg, value)
+ ((struct em_osdep *)(hw)->back)->em_flashoffset + reg, \
+ value)
#define E1000_WRITE_ICH_FLASH_REG16(hw, reg, value) \
bus_space_write_2(((struct em_osdep *)(hw)->back)->flash_bus_space_tag, \
((struct em_osdep *)(hw)->back)->flash_bus_space_handle, \
- reg, value)
+ ((struct em_osdep *)(hw)->back)->em_flashoffset + reg, \
+ value)
+
+#define E1000_WRITE_ICH_FLASH_REG32(hw, reg, value) \
+ bus_space_write_4(((struct em_osdep *)(hw)->back)->flash_bus_space_tag, \
+ ((struct em_osdep *)(hw)->back)->flash_bus_space_handle, \
+ ((struct em_osdep *)(hw)->back)->em_flashoffset + reg, \
+ value)
#define em_io_read(hw, port) \
bus_space_read_4(((struct em_osdep *)(hw)->back)->io_bus_space_tag, \