On Mon, Feb 15, 2016 at 10:37:36AM +0100, Christian Ehrhardt wrote:
> before I post the next iteration of the patch, I'd like
> some more advice on some of the points you commented (inline):

Christian Ehrhardt has asked me to port his fixes and test his new
diff on -current.  Works fine on my
em0 at pci0 dev 25 function 0 "Intel 82579LM" rev 0x04: msi, address 3c:97:...

He also asked me to commit it if diff is ok and timing still allows
it for 5.9.

bluhm

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     17 Feb 2016 13:50:36 -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 |= E1000_TARC0_CB_MULTIQ_3_REQ;
+               E1000_WRITE_REG(&sc->hw, TARC0, reg_val);
+       }
 }
 
 /*********************************************************************
@@ -3066,6 +3127,113 @@ 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);
+}
+
+/*
+ * 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
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     16 Feb 2016 17:36:22 -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  16 Feb 2016 17:38:49 -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;
@@ -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 
        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 
        }
 }
 
+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, 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 +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, 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 +9916,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 +9958,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 +10055,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 +10082,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 +10090,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
@@ -9844,7 +10133,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;
        }
@@ -9904,6 +10197,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 +10338,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 +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;
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  16 Feb 2016 17:38:49 -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 */
@@ -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 */
@@ -3728,6 +3738,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       16 Feb 2016 17:36:22 -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     16 Feb 2016 17:38:49 -0000
@@ -3347,6 +3347,8 @@ product INTEL I218_LM             0x155a  I218-LM
 product INTEL I218_V           0x1559  I218-V
 product INTEL DSL5520          0x156c  DSL5520 Thunderbolt
 product INTEL DSL5520_PCIE     0x156d  DSL5520 Thunderbolt
+product INTEL I219_LM          0x156f  I219-LM
+product INTEL I219_V           0x1570  I219-V
 product INTEL I210_COPPER_NF   0x157b  I210
 product INTEL I210_SERDES_NF   0x157c  I210 SerDes
 product INTEL I218_LM_2                0x15a0  I218-LM
@@ -3354,6 +3356,8 @@ 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 X557_AT2         0x15ad  X557-AT2
+product INTEL I219_LM2         0x15b7  I219-LM2
+product INTEL I219_V2          0x15b8  I219-V2
 product INTEL CORE5G_H_PCIE_X16        0x1601  Core 5G PCIE
 product INTEL CORE5G_M_GT1_1   0x1602  HD Graphics
 product INTEL CORE5G_HB_1      0x1604  Core 5G Host
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   16 Feb 2016 17:38:49 -0000
@@ -3352,6 +3352,8 @@
 #define        PCI_PRODUCT_INTEL_I218_V        0x1559          /* I218-V */
 #define        PCI_PRODUCT_INTEL_DSL5520       0x156c          /* DSL5520 
Thunderbolt */
 #define        PCI_PRODUCT_INTEL_DSL5520_PCIE  0x156d          /* DSL5520 
Thunderbolt */
+#define        PCI_PRODUCT_INTEL_I219_LM       0x156f          /* I219-LM */
+#define        PCI_PRODUCT_INTEL_I219_V        0x1570          /* I219-V */
 #define        PCI_PRODUCT_INTEL_I210_COPPER_NF        0x157b          /* I210 
*/
 #define        PCI_PRODUCT_INTEL_I210_SERDES_NF        0x157c          /* I210 
SerDes */
 #define        PCI_PRODUCT_INTEL_I218_LM_2     0x15a0          /* I218-LM */
@@ -3359,6 +3361,8 @@
 #define        PCI_PRODUCT_INTEL_I218_LM_3     0x15a2          /* I218-LM */
 #define        PCI_PRODUCT_INTEL_I218_V_3      0x15a3          /* I218-V */
 #define        PCI_PRODUCT_INTEL_X557_AT2      0x15ad          /* X557-AT2 */
+#define        PCI_PRODUCT_INTEL_I219_LM2      0x15b7          /* I219-LM2 */
+#define        PCI_PRODUCT_INTEL_I219_V2       0x15b8          /* I219-V2 */
 #define        PCI_PRODUCT_INTEL_CORE5G_H_PCIE_X16     0x1601          /* Core 
5G PCIE */
 #define        PCI_PRODUCT_INTEL_CORE5G_M_GT1_1        0x1602          /* HD 
Graphics */
 #define        PCI_PRODUCT_INTEL_CORE5G_HB_1   0x1604          /* Core 5G Host 
*/
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      16 Feb 2016 17:38:49 -0000
@@ -10928,6 +10928,14 @@ static const struct pci_known_product pc
            "DSL5520 Thunderbolt",
        },
        {
+           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_I210_COPPER_NF,
            "I210",
        },
@@ -10954,6 +10962,14 @@ static const struct pci_known_product pc
        {
            PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X557_AT2,
            "X557-AT2",
+       },
+       {
+           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_CORE5G_H_PCIE_X16,

Reply via email to