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