Hi,

before I post the next iteration of the patch, I'd like
some more advice on some of the points you commented (inline):

On Sun, Feb 14, 2016 at 03:34:19PM +1100, Jonathan Gray wrote:
> On Mon, Feb 08, 2016 at 01:53:20PM +0100, Christian Ehrhardt wrote:
> > 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);
> 
> This shouldn't be magic numbers, in the Intel code in FreeBSD it is:

Ok.

> |= E1000_TARC0_CB_MULTIQ_3_REQ
> 
> > +           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);
> > +}
> > +
> 
> add the comment from the Intel code here
> 
> > +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;
> 
> Isn't addr just sc->sc_tx_dma.dma_map->dm_segs[0].ds_addr ?
> Do we really need to ask the hardware for it here?

Ok.

> > +   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);
> 
> this delay is only 250 in FreeBSD

Ok.

> 
> > +}
> > +
> > +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);
> 
> This write should be above the comment to match the Intel code.
> 
> > +   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);
> > +}
> > +
> 
> comment here as well
> 
> > +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;
> 
> Odd that I219 advertises itself as I217

Hm, I didn't look at this code in detail at all. It is one of those
places where the intel code does not seem to make a difference between
I217/I218 and I219.

However, given that stuff works, this is apparently how it is...

> > @@ -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. */
> 
> not sure this comment is needed
> 

Removed. It marks the place where eeprom write code should be.
However, as eeprom write is not supported for many other chips
including the I217 ones, I guess we ignore this.

I'll get to the eeprom write code later.

> >     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;
> >  }
> 
> The latest Intel code in FreeBSD passes size as an argument to
> this function.  Should ours do the same?

Which function are you talking about? We do pass size to
em_read_ich8_data above already, em-7.5.2 does not have a size
argument to e1000_read_flash_data32_ich8lan which is the equivalent
of the function below.

> >  
> > +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
> >  }
> 
> This function is only called by em_verify_write_ich8_dword() which
> itself isn't called.  Any reason to keep either of them?

I can remove the eeprom write functions if you prefer?

The idea was that we could keep the code that is already ported
until someone (else) finds the time to add the missing bits to
the erase flash bank and function and to the  eeprom update code above
(remember the XXX comment...).

> >  
> > /******************************************************************************
> > + * 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
> >  }
> 
> In the Intel code in FreeBSD  e1000_read_flash_dword_ich8lan does the
> offset shift instead of the caller and checks if data is NULL.
> 
> That would make this function seem less pointless.

Yes, I figured that but didn't want to change the interface for
existing callers of em_read_ich8_word and these two should have
a consistent interface!

> >  
> > /******************************************************************************
> > + * 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
> 
> In addition to the ordering already mentioned use lowercase for hex digits
> in pcidevs.

Ok.

> >  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",
> >     },

Remaining open questions:
- What about the unused eeprom write code?
- Should we change the interface for em_read_ich8_{byte,word,dword}
  to match the intel code or should we stick to the current openbsd
  calling convention?
- Do we need to investigate the phy type issue (I217 vs. I219) further?

    regards    Christian

Attachment: signature.asc
Description: Digital signature

Reply via email to