Hi everyone, based on the latest release of the Intel driver for FreeBSD (em-7.5.2), I've adapted the em(4) driver to support the skylake based i219 onboard ethernet chips.
I do not have access to relevant specs, everything below is
based on reading the Intel code referenced above.
The diff was initially done for 5.7, bluhm@ did the forward port
to current. The resulting diff is below.
The major differences are:
- The NVRAM access registers are no longer in a separate BAR. Instead
they are at offset 0xe000 in the MMIO bar. As a consequence the
BAR access registers must be accessed with 32-Bit memory operations.
- There are several quirks where the i219 chips need special handling.
The most suspicious one of the quirks is where we need to flush the
tx desc ring. We use the pointer list of the tx ring as a send buffer
for a dummy packet that must be sent to flush the tx ring.
Here's a list of functions that have special handling for the
SPT based cards in the uptream intel code that I did not port
for various reasons:
- The link check code in OpenBSD differs significantly from upstream
code. Special cases for SPT based chips in em_check_for_link have
been ignored.
- e1000_check_for_copper_link_ich8lan has been ignored.
- e1000_suspend_workaroudns_ich8lan has been ignored. Suspend does
seem to work on my I219_V chip, though.
- NVRAM write is not supported for I217 based chips in OpenBSD and
the code is missing for I219 chips, too.
The patch works nicely on my I219_V chip, the other chips are
untested. I may be able to do tests with I219_LM withhin the next
few days, though.
If you own a skylake based onboard NIC, please give this diff a try.
Who should I ask for oks?
regards Christian
Index: dev/pci/if_em.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_em.c,v
retrieving revision 1.329
diff -u -p -r1.329 if_em.c
--- dev/pci/if_em.c 12 Jan 2016 00:05:21 -0000 1.329
+++ dev/pci/if_em.c 4 Feb 2016 20:33:26 -0000
@@ -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 *, bu
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
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_soft
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_soft
}
}
- 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_so
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 |= (1U << 28 | 1U << 29);
+ E1000_WRITE_REG(&sc->hw, TARC0, reg_val);
+ }
}
/*********************************************************************
@@ -3066,6 +3127,95 @@ em_disable_aspm(struct em_softc *sc)
pci_conf_write(sc->osdep.em_pa.pa_pc, sc->osdep.em_pa.pa_tag,
offset + PCI_PCIE_LCSR, val);
+}
+
+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;
+ uint64_t addr;
+
+ 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);
+
+ addr = E1000_READ_REG(&sc->hw, TDBAH);
+ addr <<= 32;
+ addr |= E1000_READ_REG(&sc->hw, TDBAL);
+
+ txd = &sc->sc_tx_desc_ring[sc->sc_tx_desc_head];
+ txd->buffer_addr = 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(500);
+}
+
+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);
+
+ /* momentarily enable the RX ring for the changes to take effect */
+ EM_WRITE_REG(&sc->hw, E1000_RXDCTL, rxdctl);
+ 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);
+}
+
+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
Index: dev/pci/if_em.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_em.h,v
retrieving revision 1.71
diff -u -p -r1.71 if_em.h
--- dev/pci/if_em.h 11 Jan 2016 01:31:53 -0000 1.71
+++ dev/pci/if_em.h 4 Feb 2016 14:39:02 -0000
@@ -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;
Index: dev/pci/if_em_hw.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_em_hw.c,v
retrieving revision 1.90
diff -u -p -r1.90 if_em_hw.c
--- dev/pci/if_em_hw.c 14 Dec 2015 03:04:10 -0000 1.90
+++ dev/pci/if_em_hw.c 4 Feb 2016 14:39:02 -0000
@@ -106,6 +106,7 @@ static int32_t em_read_ich8_byte(struct
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
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 *h
/* 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 *h
/* 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
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, uin
}
*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, uint3
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, ui
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
*/
switch (hw->mac_type) {
case em_pch_lpt:
+ case em_pch_spt:
word = EEPROM_COMPAT;
valid_csum_mask = EEPROM_COMPAT_VALID_CSUM;
break;
@@ -6813,6 +6862,7 @@ em_commit_shadow_ram(struct em_hw *hw)
return -E1000_ERR_EEPROM;
}
}
+ /* XXX CEH: Some code for eeprom write is missing. */
if ((hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) &&
hw->eeprom_shadow_ram != NULL) {
/*
@@ -7131,7 +7181,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 +7738,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 +7880,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 +9073,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 +9432,45 @@ em_valid_nvm_bank_detect_ich8lan(struct
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 +9517,92 @@ em_valid_nvm_bank_detect_ich8lan(struct
}
}
+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 +9629,9 @@ em_read_eeprom_ich8(struct em_hw *hw, ui
* 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 +9736,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 +9753,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 +9778,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 +9791,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 +9809,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 +9834,31 @@ em_ich8_flash_cycle(struct em_hw *hw, ui
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 +9917,7 @@ em_read_ich8_data(struct em_hw *hw, uint
*/
/* 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 +9959,88 @@ em_read_ich8_data(struct em_hw *hw, uint
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 +10056,8 @@ em_write_ich8_data(struct em_hw *hw, uin
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 +10083,7 @@ em_write_ich8_data(struct em_hw *hw, uin
* 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 +10091,7 @@ em_write_ich8_data(struct em_hw *hw, uin
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
@@ -9833,6 +10123,82 @@ em_write_ich8_data(struct em_hw *hw, uin
}
/******************************************************************************
+ * Writes four bytes to the NVM using the ICH8 flash access registers.
+ *
+ * hw - The pointer to the hw structure
+ * index - The index of the dword to write.
+ * data - The byte(s) to write to the NVM.
+ *****************************************************************************/
+STATIC int32_t
+em_write_ich8_data32(struct em_hw *hw, uint32_t index, 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;
+ int32_t count = 0;
+ DEBUGFUNC("em_write_ich8_data");
+
+ if (hw->mac_type != em_pch_spt)
+ return error;
+ if (index > ICH_FLASH_LINEAR_ADDR_MASK)
+ return error;
+ flash_linear_address = (ICH_FLASH_LINEAR_ADDR_MASK & index) +
+ hw->flash_base_addr;
+
+ do {
+ usec_delay(1);
+ /* Steps */
+ error = em_ich8_cycle_init(hw);
+ if (error)
+ break;
+
+ 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_WRITE;
+ E1000_WRITE_ICH_FLASH_REG32(hw, ICH_FLASH_HSFCTL,
+ (uint32_t)hsflctl.regval << 16);
+ /*
+ * Write the last 24 bits of index into Flash Linear address
+ * field in Flash Address
+ */
+ E1000_WRITE_ICH_FLASH_REG32(hw, ICH_FLASH_FADDR,
+ flash_linear_address);
+
+ E1000_WRITE_ICH_FLASH_REG32(hw, ICH_FLASH_FDATA0, 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
+ */
+ error = em_ich8_flash_cycle(hw,
+ ICH_FLASH_COMMAND_TIMEOUT);
+ if (error == E1000_SUCCESS)
+ break;
+
+ /*
+ * If we're here, then things are most likely
+ * 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_REG32(hw,
+ ICH_FLASH_HSFSTS) & 0xffffUL;
+ if (hsfsts.hsf_status.flcerr == 1)
+ /* Repeat for some time before giving up. */
+ continue;
+ if (hsfsts.hsf_status.flcdone == 0) {
+ DEBUGOUT("Timeout error - flash cycle did not"
+ " complete.");
+ break;
+ }
+ } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
+
+ return error;
+}
+
+/******************************************************************************
* Reads a single byte from the NVM using the ICH8 flash access registers.
*
* hw - pointer to em_hw structure
@@ -9844,7 +10210,11 @@ em_read_ich8_byte(struct em_hw *hw, uint
{
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;
}
@@ -9887,6 +10257,39 @@ em_verify_write_ich8_byte(struct em_hw *
}
/******************************************************************************
+ * Writes a single dword to the NVM using the ICH8 flash access registers.
+ * Performs verification by reading back the value and then going through
+ * a retry algorithm before giving up.
+ *
+ * hw - pointer to em_hw structure
+ * index - The byte index of the dword to write.
+ * byte - The byte to write to the NVM.
+ *****************************************************************************/
+STATIC int32_t
+em_verify_write_ich8_dword(struct em_hw *hw, uint32_t index, uint32_t dword)
+{
+ int32_t error = E1000_SUCCESS;
+ int32_t program_retries = 0;
+ DEBUGOUT2("Dword := %8.8X Offset := %d\n", dword, index);
+
+ error = em_write_ich8_data32(hw, index, dword);
+
+ if (E1000_SUCCESS)
+ return error;
+ for (program_retries = 0; program_retries < 100; program_retries++) {
+ DEBUGOUT2("Retrying \t Byte := %8.8X Offset := %d\n",
+ dword, index);
+ error = em_write_ich8_data32(hw, index, dword);
+ if (error == E1000_SUCCESS)
+ break;
+ }
+ if (program_retries == 100)
+ error = E1000_ERR_EEPROM;
+
+ return error;
+}
+
+/******************************************************************************
* Writes a single byte to the NVM using the ICH8 flash access registers.
*
* hw - pointer to em_hw structure
@@ -9904,6 +10307,21 @@ em_write_ich8_byte(struct em_hw *hw, uin
}
/******************************************************************************
+ * 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 +10448,7 @@ em_erase_ich8_4k_segment(struct em_hw *h
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 +10648,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;
Index: dev/pci/if_em_hw.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_em_hw.h,v
retrieving revision 1.67
diff -u -p -r1.67 if_em_hw.h
--- dev/pci/if_em_hw.h 12 Sep 2015 02:38:14 -0000 1.67
+++ dev/pci/if_em_hw.h 4 Feb 2016 14:39:02 -0000
@@ -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
#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 */
@@ -3728,6 +3735,15 @@ union ich8_hws_flash_regacc {
#define I2_SMBUS_CTRL PHY_REG(769, 23)
#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
Index: dev/pci/if_em_osdep.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_em_osdep.h,v
retrieving revision 1.12
diff -u -p -r1.12 if_em_osdep.h
--- dev/pci/if_em_osdep.h 5 Oct 2011 02:52:10 -0000 1.12
+++ dev/pci/if_em_osdep.h 4 Feb 2016 14:39:02 -0000
@@ -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,31 @@ 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, \
Index: dev/pci/pcidevs
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/pcidevs,v
retrieving revision 1.1786
diff -u -p -r1.1786 pcidevs
--- dev/pci/pcidevs 30 Jan 2016 01:02:04 -0000 1.1786
+++ dev/pci/pcidevs 4 Feb 2016 16:04:31 -0000
@@ -3353,6 +3353,10 @@ product INTEL I218_LM_2 0x15a0 I218-LM
product INTEL I218_V_2 0x15a1 I218-V
product INTEL I218_LM_3 0x15a2 I218-LM
product INTEL I218_V_3 0x15a3 I218-V
+product INTEL I219_LM 0x156F I219_LM
+product INTEL I219_V 0x1570 I219_V
+product INTEL I219_LM2 0x15B7 I219_LM2
+product INTEL I219_V2 0x15B8 I219_V2
product INTEL X557_AT2 0x15ad X557-AT2
product INTEL CORE5G_H_PCIE_X16 0x1601 Core 5G PCIE
product INTEL CORE5G_M_GT1_1 0x1602 HD Graphics
Index: dev/pci/pcidevs.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/pcidevs.h,v
retrieving revision 1.1779
diff -u -p -r1.1779 pcidevs.h
--- dev/pci/pcidevs.h 30 Jan 2016 01:02:39 -0000 1.1779
+++ dev/pci/pcidevs.h 4 Feb 2016 16:04:42 -0000
@@ -3358,6 +3358,10 @@
#define PCI_PRODUCT_INTEL_I218_V_2 0x15a1 /* I218-V */
#define PCI_PRODUCT_INTEL_I218_LM_3 0x15a2 /* I218-LM */
#define PCI_PRODUCT_INTEL_I218_V_3 0x15a3 /* I218-V */
+#define PCI_PRODUCT_INTEL_I219_LM 0x156F /* I219_LM */
+#define PCI_PRODUCT_INTEL_I219_V 0x1570 /* I219_V */
+#define PCI_PRODUCT_INTEL_I219_LM2 0x15B7 /* I219_LM2 */
+#define PCI_PRODUCT_INTEL_I219_V2 0x15B8 /* I219_V2 */
#define PCI_PRODUCT_INTEL_X557_AT2 0x15ad /* X557-AT2 */
#define PCI_PRODUCT_INTEL_CORE5G_H_PCIE_X16 0x1601 /* Core
5G PCIE */
#define PCI_PRODUCT_INTEL_CORE5G_M_GT1_1 0x1602 /* HD
Graphics */
Index: dev/pci/pcidevs_data.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/pcidevs_data.h,v
retrieving revision 1.1774
diff -u -p -r1.1774 pcidevs_data.h
--- dev/pci/pcidevs_data.h 30 Jan 2016 01:02:39 -0000 1.1774
+++ dev/pci/pcidevs_data.h 4 Feb 2016 16:04:42 -0000
@@ -10952,6 +10952,22 @@ static const struct pci_known_product pc
"I218-V",
},
{
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM,
+ "I219_LM",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V,
+ "I219_V",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM2,
+ "I219_LM2",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V2,
+ "I219_V2",
+ },
+ {
PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X557_AT2,
"X557-AT2",
},
signature.asc
Description: Digital signature
