diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2006-07-07 02:56:19 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2006-07-07 02:56:19 +0000 |
commit | a2fe356796115a700ec497a65bfdef58b23ff466 (patch) | |
tree | 784cf41e5a17d12026f47d87dba73d245e801d25 /sys/dev | |
parent | e8f94f74c0af0f445dedd4ceac1c53a524869ffb (diff) |
Sync up to Intel's latest FreeBSD em driver (6.0.5). Adds support
for new chipset revisions embedded in the ESB2 and ICH8 core logic
chipsets.
The previous attempt at commiting this included an unrelated change
to how the I/O base address was being set and this was the cause of
the breakage.
From: Intel's web-site
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_em.c | 159 | ||||
-rw-r--r-- | sys/dev/pci/if_em.h | 24 | ||||
-rw-r--r-- | sys/dev/pci/if_em_hw.c | 2840 | ||||
-rw-r--r-- | sys/dev/pci/if_em_hw.h | 421 | ||||
-rw-r--r-- | sys/dev/pci/if_em_osdep.h | 96 |
5 files changed, 2761 insertions, 779 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c index f14d9f900c1..6a9e2c269c6 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.135 2006/07/05 01:15:30 brad Exp $ */ +/* $OpenBSD: if_em.c,v 1.136 2006/07/07 02:56:18 brad Exp $ */ /* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */ #include <dev/pci/if_em.h> @@ -45,7 +45,7 @@ int em_display_debug_stats = 0; * Driver version *********************************************************************/ -char em_driver_version[] = "5.1.5"; +char em_driver_version[] = "6.0.5"; /********************************************************************* * PCI Device ID Table @@ -53,6 +53,8 @@ char em_driver_version[] = "5.1.5"; const struct pci_matchid em_devices[] = { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80003ES2LAN_CPR_DPT }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80003ES2LAN_SDS_DPT }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80003ES2LAN_CPR_SPT }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80003ES2LAN_SDS_SPT }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EM }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EM_LOM }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EP }, @@ -106,7 +108,12 @@ const struct pci_matchid em_devices[] = { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573L }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573L_PL_1 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573L_PL_2 }, - { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573V_PM } + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573V_PM }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IGP_M_AMT }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IGP_AMT }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IGP_C }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IFE }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IGP_M } }; /********************************************************************* @@ -182,6 +189,8 @@ struct cfdriver em_cd = { 0, "em", DV_IFNET }; +static int em_smart_pwr_down = FALSE; + /********************************************************************* * Device identification routine * @@ -290,6 +299,10 @@ em_attach(struct device *parent, struct device *self, void *aux) case em_80003es2lan: /* Limit Jumbo Frame size */ sc->hw.max_frame_size = 9234; break; + case em_ich8lan: + /* ICH8 does not support jumbo frames */ + sc->hw.max_frame_size = ETHER_MAX_LEN; + break; default: sc->hw.max_frame_size = MAX_JUMBO_FRAME_SIZE; @@ -300,10 +313,10 @@ em_attach(struct device *parent, struct device *self, void *aux) if (sc->hw.mac_type >= em_82544) tsize = EM_ROUNDUP(sc->num_tx_desc * sizeof(struct em_tx_desc), - EM_MAX_TXD_82544 * sizeof(struct em_tx_desc)); + EM_MAX_TXD * sizeof(struct em_tx_desc)); else tsize = EM_ROUNDUP(sc->num_tx_desc * sizeof(struct em_tx_desc), - EM_MAX_TXD * sizeof(struct em_tx_desc)); + EM_MAX_TXD_82543 * sizeof(struct em_tx_desc)); tsize = EM_ROUNDUP(tsize, PAGE_SIZE); /* Allocate Transmit Descriptor ring */ @@ -602,9 +615,9 @@ em_init(void *arg) if (ifp->if_flags & IFF_UP) { if (sc->hw.mac_type >= em_82544) - sc->num_tx_desc = EM_MAX_TXD_82544; - else sc->num_tx_desc = EM_MAX_TXD; + else + sc->num_tx_desc = EM_MAX_TXD_82543; sc->num_rx_desc = EM_MAX_RXD; } else { sc->num_tx_desc = EM_MIN_TXD; @@ -615,6 +628,12 @@ em_init(void *arg) /* Packet Buffer Allocation (PBA) * Writing PBA sets the receive portion of the buffer * the remainder is used for the transmit buffer. + * + * Devices before the 82547 had a Packet Buffer of 64K. + * Default allocation: PBA=48K for Rx, leaving 16K for Tx. + * After the 82547 the buffer was reduced to 40K. + * Default allocation: PBA=30K for Rx, leaving 10K for Tx. + * Note: default does not leave enough room for Jumbo Frame >10k. */ switch (sc->hw.mac_type) { case em_82547: @@ -636,6 +655,9 @@ em_init(void *arg) /* Jumbo frames not supported */ pba = E1000_PBA_12K; /* 12K for Rx, 20K for Tx */ break; + case em_ich8lan: + pba = E1000_PBA_8K; + break; default: /* Devices before 82547 had a Packet Buffer of 64K. */ if (sc->hw.max_frame_size > EM_RXBUFFER_8192) @@ -1246,6 +1268,8 @@ em_local_timer(void *arg) splx(s); } +#define SPEED_MODE_BIT (1<<21) /* On PCI-E MACs only */ + void em_update_link_status(struct em_softc *sc) { @@ -1256,6 +1280,15 @@ em_update_link_status(struct em_softc *sc) em_get_speed_and_duplex(&sc->hw, &sc->link_speed, &sc->link_duplex); + /* Check if we may set SPEED_MODE bit on PCI-E */ + if ((sc->link_speed == SPEED_1000) && + ((sc->hw.mac_type == em_82571) || + (sc->hw.mac_type == em_82572))) { + int tarc0; + tarc0 = E1000_READ_REG(&sc->hw, TARC0); + tarc0 |= SPEED_MODE_BIT; + E1000_WRITE_REG(&sc->hw, TARC0, tarc0); + } sc->link_active = 1; sc->smartspeed = 0; ifp->if_baudrate = sc->link_speed * 1000000; @@ -1371,11 +1404,10 @@ em_allocate_pci_resources(struct em_softc *sc) PCI_MAPREG_MEM_TYPE_64BIT) rid += 4; /* skip high bits, too */ } + if (pci_mapreg_map(pa, rid, PCI_MAPREG_TYPE_IO, 0, - &sc->osdep.em_iobtag, - &sc->osdep.em_iobhandle, - &sc->osdep.em_iobase, - &sc->osdep.em_iosize, 0)) { + &sc->osdep.io_bus_space_tag, &sc->osdep.io_bus_space_handle, + &sc->osdep.em_iobase, &sc->osdep.em_iosize, 0)) { printf(": can't find io space\n"); return (ENXIO); } @@ -1383,6 +1415,22 @@ em_allocate_pci_resources(struct em_softc *sc) sc->hw.io_base = 0; } + /* for ICH8 we need to find the flash memory */ + if (sc->hw.mac_type == em_ich8lan) { + val = pci_conf_read(pa->pa_pc, pa->pa_tag, EM_FLASH); + if (PCI_MAPREG_TYPE(val) != PCI_MAPREG_TYPE_MEM) { + printf(": flash isn't memory"); + return (ENXIO); + } + + if (pci_mapreg_map(pa, EM_FLASH, PCI_MAPREG_MEM_TYPE(val), 0, + &sc->osdep.flash_bus_space_tag, &sc->osdep.flash_bus_space_handle, + &sc->osdep.em_flashbase, &sc->osdep.em_flashsize, 0)) { + printf(": can't find mem space\n"); + return (ENXIO); + } + } + if (pci_intr_map(pa, &ih)) { printf(": couldn't map interrupt\n"); return (ENXIO); @@ -1411,16 +1459,21 @@ em_free_pci_resources(struct em_softc *sc) struct pci_attach_args *pa = &sc->osdep.em_pa; pci_chipset_tag_t pc = pa->pa_pc; - if(sc->sc_intrhand) + if (sc->sc_intrhand) pci_intr_disestablish(pc, sc->sc_intrhand); sc->sc_intrhand = 0; - if(sc->osdep.em_iobase) - bus_space_unmap(sc->osdep.em_iobtag, sc->osdep.em_iobhandle, + if (sc->osdep.em_flashbase) + bus_space_unmap(sc->osdep.flash_bus_space_tag, sc->osdep.flash_bus_space_handle, + sc->osdep.em_flashsize); + sc->osdep.em_flashbase = 0; + + if (sc->osdep.em_iobase) + bus_space_unmap(sc->osdep.io_bus_space_tag, sc->osdep.io_bus_space_handle, sc->osdep.em_iosize); sc->osdep.em_iobase = 0; - if(sc->osdep.em_membase) + if (sc->osdep.em_membase) bus_space_unmap(sc->osdep.mem_bus_space_tag, sc->osdep.mem_bus_space_handle, sc->osdep.em_memsize); sc->osdep.em_membase = 0; @@ -1459,6 +1512,17 @@ em_hardware_init(struct em_softc *sc) return (EIO); } + /* Set up smart power down as default off on newer adapters */ + if (!em_smart_pwr_down && + (sc->hw.mac_type == em_82571 || + sc->hw.mac_type == em_82572)) { + uint16_t phy_tmp = 0; + /* speed up time to link by disabling smart power down */ + em_read_phy_reg(&sc->hw, IGP02E1000_PHY_POWER_MGMT, &phy_tmp); + phy_tmp &= ~IGP02E1000_PM_SPD; + em_write_phy_reg(&sc->hw, IGP02E1000_PHY_POWER_MGMT, phy_tmp); + } + /* * These parameters control the automatic generation (Tx) and * response (Rx) to Ethernet PAUSE frames. @@ -1750,22 +1814,22 @@ em_setup_transmit_structures(struct em_softc *sc) void em_initialize_transmit_unit(struct em_softc *sc) { - u_int32_t reg_tctl, tarc; + u_int32_t reg_tctl, reg_tarc; u_int32_t reg_tipg = 0; u_int64_t bus_addr; INIT_DEBUGOUT("em_initialize_transmit_unit: begin"); /* Setup the Base and Length of the Tx Descriptor Ring */ bus_addr = sc->txdma.dma_map->dm_segs[0].ds_addr; - E1000_WRITE_REG(&sc->hw, TDBAL, (u_int32_t)bus_addr); - E1000_WRITE_REG(&sc->hw, TDBAH, (u_int32_t)(bus_addr >> 32)); E1000_WRITE_REG(&sc->hw, TDLEN, sc->num_tx_desc * sizeof(struct em_tx_desc)); + E1000_WRITE_REG(&sc->hw, TDBAH, (u_int32_t)(bus_addr >> 32)); + E1000_WRITE_REG(&sc->hw, TDBAL, (u_int32_t)bus_addr); /* Setup the HW Tx Head and Tail descriptor pointers */ - E1000_WRITE_REG(&sc->hw, TDH, 0); E1000_WRITE_REG(&sc->hw, TDT, 0); + E1000_WRITE_REG(&sc->hw, TDH, 0); HW_DEBUGOUT2("Base = %x, Length = %x\n", E1000_READ_REG(&sc->hw, TDBAL), @@ -1797,6 +1861,26 @@ em_initialize_transmit_unit(struct em_softc *sc) if(sc->hw.mac_type >= em_82540) E1000_WRITE_REG(&sc->hw, TADV, sc->tx_abs_int_delay); + /* Do adapter specific tweaks before we enable the transmitter */ + if (sc->hw.mac_type == em_82571 || sc->hw.mac_type == em_82572) { + reg_tarc = E1000_READ_REG(&sc->hw, TARC0); + reg_tarc |= (1 << 25); + E1000_WRITE_REG(&sc->hw, TARC0, reg_tarc); + reg_tarc = E1000_READ_REG(&sc->hw, TARC1); + reg_tarc |= (1 << 25); + reg_tarc &= ~(1 << 28); + E1000_WRITE_REG(&sc->hw, TARC1, reg_tarc); + } else if (sc->hw.mac_type == em_80003es2lan) { + reg_tarc = E1000_READ_REG(&sc->hw, TARC0); + reg_tarc |= 1; + if (sc->hw.media_type == em_media_type_internal_serdes) + reg_tarc |= (1 << 20); + E1000_WRITE_REG(&sc->hw, TARC0, reg_tarc); + reg_tarc = E1000_READ_REG(&sc->hw, TARC1); + reg_tarc |= 1; + E1000_WRITE_REG(&sc->hw, TARC1, reg_tarc); + } + /* Program the Transmit Control Register */ reg_tctl = E1000_TCTL_PSP | E1000_TCTL_EN | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); @@ -1806,30 +1890,9 @@ em_initialize_transmit_unit(struct em_softc *sc) reg_tctl |= E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT; else 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); - if (sc->hw.mac_type == em_82571 || sc->hw.mac_type == em_82572) { - tarc = E1000_READ_REG(&sc->hw, TARC0); - tarc |= ((1 << 25) | (1 << 21)); - E1000_WRITE_REG(&sc->hw, TARC0, tarc); - tarc = E1000_READ_REG(&sc->hw, TARC1); - tarc |= (1 << 25); - if (reg_tctl & E1000_TCTL_MULR) - tarc &= ~(1 << 28); - else - tarc |= (1 << 28); - E1000_WRITE_REG(&sc->hw, TARC1, tarc); - } else if (sc->hw.mac_type == em_80003es2lan) { - tarc = E1000_READ_REG(&sc->hw, TARC0); - tarc |= 1; - if (sc->hw.media_type == em_media_type_internal_serdes) - tarc |= (1 << 20); - E1000_WRITE_REG(&sc->hw, TARC0, tarc); - tarc = E1000_READ_REG(&sc->hw, TARC1); - tarc |= 1; - E1000_WRITE_REG(&sc->hw, TARC1, tarc); - } - /* Setup Transmit Descriptor Settings for this adapter */ sc->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_RS; @@ -2186,14 +2249,14 @@ em_initialize_receive_unit(struct em_softc *sc) /* Setup the Base and Length of the Rx Descriptor Ring */ bus_addr = sc->rxdma.dma_map->dm_segs[0].ds_addr; - E1000_WRITE_REG(&sc->hw, RDBAL, (u_int32_t)bus_addr); - E1000_WRITE_REG(&sc->hw, RDBAH, (u_int32_t)(bus_addr >> 32)); E1000_WRITE_REG(&sc->hw, RDLEN, sc->num_rx_desc * sizeof(struct em_rx_desc)); + E1000_WRITE_REG(&sc->hw, RDBAH, (u_int32_t)(bus_addr >> 32)); + E1000_WRITE_REG(&sc->hw, RDBAL, (u_int32_t)bus_addr); /* Setup the HW Rx Head and Tail Descriptor Pointers */ - E1000_WRITE_REG(&sc->hw, RDH, 0); E1000_WRITE_REG(&sc->hw, RDT, sc->num_rx_desc - 1); + E1000_WRITE_REG(&sc->hw, RDH, 0); /* Setup the Receive Control Register */ reg_rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | @@ -2735,7 +2798,7 @@ em_update_stats_counters(struct em_softc *sc) sc->stats.rxerrc + sc->stats.crcerrs + sc->stats.algnerrc + - sc->stats.rlec + sc->stats.rnbc + + sc->stats.ruc + sc->stats.roc + sc->stats.mpc + sc->stats.cexterr + sc->rx_overruns; @@ -2769,8 +2832,10 @@ em_print_hw_stats(struct em_softc *sc) (long long)sc->stats.mpc); printf("%s: Receive No Buffers = %lld\n", unit, (long long)sc->stats.rnbc); - printf("%s: Receive length errors = %lld\n", unit, - (long long)sc->stats.rlec); + /* RLEC is inaccurate on some hardware, calculate our own */ + printf("%s: Receive Length Errors = %lld\n", unit, + ((long long)sc->stats.roc + + (long long)sc->stats.ruc)); printf("%s: Receive errors = %lld\n", unit, (long long)sc->stats.rxerrc); printf("%s: Crc errors = %lld\n", unit, diff --git a/sys/dev/pci/if_em.h b/sys/dev/pci/if_em.h index 0b33d845868..af01b8a70c3 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.25 2006/07/05 01:15:30 brad Exp $ */ +/* $OpenBSD: if_em.h,v 1.26 2006/07/07 02:56:18 brad Exp $ */ #ifndef _EM_H_DEFINED_ #define _EM_H_DEFINED_ @@ -83,20 +83,23 @@ POSSIBILITY OF SUCH DAMAGE. /* Tunables */ /* - * EM_(MIN/MAX)_TXD: Maximum number of Transmit Descriptors + * EM_TXD: Maximum number of Transmit Descriptors * Valid Range: 80-256 for 82542 and 82543-based adapters * 80-4096 for others * Default Value: 256 * This value is the number of transmit descriptors allocated by the driver. * Increasing this value allows the driver to queue more transmits. Each * descriptor is 16 bytes. + * Since TDLEN should be multiple of 128bytes, the number of transmit + * desscriptors should meet the following condition. + * (num_tx_desc * sizeof(struct em_tx_desc)) % 128 == 0 */ #define EM_MIN_TXD 12 -#define EM_MAX_TXD 256 -#define EM_MAX_TXD_82544 512 +#define EM_MAX_TXD_82543 256 +#define EM_MAX_TXD 512 /* - * EM_(MIN/MAX)_RXD - Maximum number of receive Descriptors + * EM_RXD - Maximum number of receive Descriptors * Valid Range: 80-256 for 82542 and 82543-based adapters * 80-4096 for others * Default Value: 256 @@ -104,7 +107,9 @@ POSSIBILITY OF SUCH DAMAGE. * Increasing this value allows the driver to buffer more incoming packets. * Each descriptor is 16 bytes. A receive buffer is also allocated for each * descriptor. The maximum MTU size is 16110. - * + * Since TDLEN should be multiple of 128bytes, the number of transmit + * desscriptors should meet the following condition. + * (num_tx_desc * sizeof(struct em_tx_desc)) % 128 == 0 */ #define EM_MIN_RXD 12 #define EM_MAX_RXD 256 @@ -213,6 +218,7 @@ POSSIBILITY OF SUCH DAMAGE. ADVERTISE_1000_FULL) #define EM_MMBA 0x0010 /* Mem base address */ +#define EM_FLASH 0x0014 /* Flash memory on ICH8 */ #define EM_ROUNDUP(size, unit) (((size) + (unit) - 1) & ~((unit) - 1)) #define EM_SMARTSPEED_DOWNSHIFT 3 @@ -303,12 +309,6 @@ struct em_softc { void *sc_powerhook; void *sc_shutdownhook; -#ifdef __STRICT_ALIGNMENT - /* Used for carrying forward alignment adjustments */ - unsigned char align_buf[ETHER_ALIGN]; /* tail of unaligned packet */ - u_int8_t align_buf_len; /* bytes in tail */ -#endif /* __STRICT_ALIGNMENT */ - /* Info about the board itself */ u_int32_t part_num; u_int8_t link_active; diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c index f6b1105d0fa..d0e382b0738 100644 --- a/sys/dev/pci/if_em_hw.c +++ b/sys/dev/pci/if_em_hw.c @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ -/* $OpenBSD: if_em_hw.c,v 1.20 2006/07/05 01:15:30 brad Exp $ */ +/* $OpenBSD: if_em_hw.c,v 1.21 2006/07/07 02:56:18 brad Exp $ */ /* if_em_hw.c * Shared functions for accessing and configuring the MAC @@ -41,7 +41,7 @@ POSSIBILITY OF SUCH DAMAGE. #include <sys/cdefs.h> __FBSDID("$FreeBSD: if_em_hw.c,v 1.16 2005/05/26 23:32:02 tackerman Exp $"); #endif - + #include <sys/param.h> #include <sys/systm.h> #include <sys/sockio.h> @@ -64,7 +64,7 @@ __FBSDID("$FreeBSD: if_em_hw.c,v 1.16 2005/05/26 23:32:02 tackerman Exp $"); #endif #include <uvm/uvm_extern.h> - + #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> @@ -107,8 +107,9 @@ static int32_t em_polarity_reversal_workaround(struct em_hw *hw); static int32_t em_set_phy_mode(struct em_hw *hw); static int32_t em_host_if_read_cookie(struct em_hw *hw, uint8_t *buffer); static uint8_t em_calculate_mng_checksum(char *buffer, uint32_t length); -static int32_t em_configure_kmrn_for_10_100(struct em_hw *hw, uint16_t duplex); -static int32_t em_configure_kmrn_for_1000(struct em_hw *hw, uint16_t duplex); +static int32_t em_configure_kmrn_for_10_100(struct em_hw *hw, + uint16_t duplex); +static int32_t em_configure_kmrn_for_1000(struct em_hw *hw); /* IGP cable length table */ static const @@ -143,10 +144,10 @@ em_set_phy_type(struct em_hw *hw) { DEBUGFUNC("em_set_phy_type"); - if(hw->mac_type == em_undefined) + if (hw->mac_type == em_undefined) return -E1000_ERR_PHY_TYPE; - switch(hw->phy_id) { + switch (hw->phy_id) { case M88E1000_E_PHY_ID: case M88E1000_I_PHY_ID: case M88E1011_I_PHY_ID: @@ -154,13 +155,21 @@ em_set_phy_type(struct em_hw *hw) hw->phy_type = em_phy_m88; break; case IGP01E1000_I_PHY_ID: - if(hw->mac_type == em_82541 || - hw->mac_type == em_82541_rev_2 || - hw->mac_type == em_82547 || - hw->mac_type == em_82547_rev_2) { + if (hw->mac_type == em_82541 || + hw->mac_type == em_82541_rev_2 || + hw->mac_type == em_82547 || + hw->mac_type == em_82547_rev_2) { hw->phy_type = em_phy_igp; break; } + case IGP03E1000_E_PHY_ID: + hw->phy_type = em_phy_igp_3; + break; + case IFE_E_PHY_ID: + case IFE_PLUS_E_PHY_ID: + case IFE_C_E_PHY_ID: + hw->phy_type = em_phy_ife; + break; case GG82563_E_PHY_ID: if (hw->mac_type == em_80003es2lan) { hw->phy_type = em_phy_gg82563; @@ -189,7 +198,7 @@ em_phy_init_script(struct em_hw *hw) DEBUGFUNC("em_phy_init_script"); - if(hw->phy_init_script) { + if (hw->phy_init_script) { msec_delay(20); /* Save off the current value of register 0x2F5B to be restored at @@ -205,7 +214,7 @@ em_phy_init_script(struct em_hw *hw) msec_delay(5); - switch(hw->mac_type) { + switch (hw->mac_type) { case em_82541: case em_82547: em_write_phy_reg(hw, 0x1F95, 0x0001); @@ -242,22 +251,22 @@ em_phy_init_script(struct em_hw *hw) /* Now enable the transmitter */ em_write_phy_reg(hw, 0x2F5B, phy_saved_data); - if(hw->mac_type == em_82547) { + if (hw->mac_type == em_82547) { uint16_t fused, fine, coarse; /* Move to analog registers page */ em_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused); - if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { + if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { em_read_phy_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS, &fused); fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK; coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK; - if(coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) { + if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) { coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10; fine -= IGP01E1000_ANALOG_FUSE_FINE_1; - } else if(coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH) + } else if (coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH) fine -= IGP01E1000_ANALOG_FUSE_FINE_10; fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | @@ -337,8 +346,8 @@ em_set_mac_type(struct em_hw *hw) hw->mac_type = em_82546_rev_3; break; case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541ER_LOM: case E1000_DEV_ID_82541EI_MOBILE: + case E1000_DEV_ID_82541ER_LOM: hw->mac_type = em_82541; break; case E1000_DEV_ID_82541ER: @@ -377,16 +386,29 @@ em_set_mac_type(struct em_hw *hw) case E1000_DEV_ID_82573V_PM: hw->mac_type = em_82573; break; + case E1000_DEV_ID_80003ES2LAN_COPPER_SPT: + case E1000_DEV_ID_80003ES2LAN_SERDES_SPT: case E1000_DEV_ID_80003ES2LAN_COPPER_DPT: case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: hw->mac_type = em_80003es2lan; break; + case E1000_DEV_ID_ICH8_IGP_M_AMT: + case E1000_DEV_ID_ICH8_IGP_AMT: + case E1000_DEV_ID_ICH8_IGP_C: + case E1000_DEV_ID_ICH8_IFE: + case E1000_DEV_ID_ICH8_IGP_M: + hw->mac_type = em_ich8lan; + break; default: /* Should never have loaded on this device */ return -E1000_ERR_MAC_TYPE; } - switch(hw->mac_type) { + switch (hw->mac_type) { + case em_ich8lan: + hw->swfwhw_semaphore_present = TRUE; + hw->asf_firmware_present = TRUE; + break; case em_80003es2lan: hw->swfw_sync_present = TRUE; /* FALLTHROUGH */ @@ -420,7 +442,7 @@ em_set_media_type(struct em_hw *hw) DEBUGFUNC("em_set_media_type"); - if(hw->mac_type != em_82543) { + if (hw->mac_type != em_82543) { /* tbi_compatibility is only valid on 82543 */ hw->tbi_compatibility_en = FALSE; } @@ -439,6 +461,7 @@ em_set_media_type(struct em_hw *hw) case em_82542_rev2_1: hw->media_type = em_media_type_fiber; break; + case em_ich8lan: case em_82573: /* The STATUS_TBIMODE bit is reserved or reused for the this * device. @@ -479,16 +502,16 @@ em_reset_hw(struct em_hw *hw) DEBUGFUNC("em_reset_hw"); /* For 82542 (rev 2.0), disable MWI before issuing a device reset */ - if(hw->mac_type == em_82542_rev2_0) { + if (hw->mac_type == em_82542_rev2_0) { DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); em_pci_clear_mwi(hw); } - if(hw->bus_type == em_bus_type_pci_express) { + if (hw->bus_type == em_bus_type_pci_express) { /* Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ - if(em_disable_pciex_master(hw) != E1000_SUCCESS) { + if (em_disable_pciex_master(hw) != E1000_SUCCESS) { DEBUGOUT("PCI-E Master disable polling has failed.\n"); } } @@ -516,14 +539,14 @@ em_reset_hw(struct em_hw *hw) ctrl = E1000_READ_REG(hw, CTRL); /* Must reset the PHY before resetting the MAC */ - if((hw->mac_type == em_82541) || (hw->mac_type == em_82547)) { + if ((hw->mac_type == em_82541) || (hw->mac_type == em_82547)) { E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST)); msec_delay(5); } /* Must acquire the MDIO ownership before MAC reset. * Ownership defaults to firmware after a reset. */ - if(hw->mac_type == em_82573) { + if (hw->mac_type == em_82573) { timeout = 10; extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL); @@ -533,14 +556,22 @@ em_reset_hw(struct em_hw *hw) E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl); extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL); - if(extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) + if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) break; else extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; msec_delay(2); timeout--; - } while(timeout); + } while (timeout); + } + + /* Workaround for ICH8 bit corruption issue in FIFO memory */ + if (hw->mac_type == em_ich8lan) { + /* Set Tx and Rx buffer allocation to 8k apiece. */ + E1000_WRITE_REG(hw, PBA, E1000_PBA_8K); + /* Set Packet Buffer Size to 16k. */ + E1000_WRITE_REG(hw, PBS, E1000_PBS_16K); } /* Issue a global reset to the MAC. This will reset the chip's @@ -550,7 +581,7 @@ em_reset_hw(struct em_hw *hw) */ DEBUGOUT("Issuing a global reset to MAC\n"); - switch(hw->mac_type) { + switch (hw->mac_type) { case em_82544: case em_82540: case em_82545: @@ -566,6 +597,20 @@ em_reset_hw(struct em_hw *hw) /* Reset is performed on a shadow of the control register */ E1000_WRITE_REG(hw, CTRL_DUP, (ctrl | E1000_CTRL_RST)); break; + case em_ich8lan: + if (!hw->phy_reset_disable && + em_check_phy_reset_block(hw) == E1000_SUCCESS) { + /* em_ich8lan PHY HW reset requires MAC CORE reset + * at the same time to make sure the interface between + * MAC and the external PHY is reset. + */ + ctrl |= E1000_CTRL_PHY_RST; + } + + em_get_software_flag(hw); + E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); + msec_delay(5); + break; default: E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); break; @@ -575,7 +620,7 @@ em_reset_hw(struct em_hw *hw) * device. Later controllers reload the EEPROM automatically, so just wait * for reload to complete. */ - switch(hw->mac_type) { + switch (hw->mac_type) { case em_82542_rev2_0: case em_82542_rev2_1: case em_82543: @@ -607,9 +652,10 @@ em_reset_hw(struct em_hw *hw) /* FALLTHROUGH */ case em_82571: case em_82572: + case em_ich8lan: case em_80003es2lan: ret_val = em_get_auto_rd_done(hw); - if(ret_val) + if (ret_val) /* We don't want to continue accessing MAC registers. */ return ret_val; break; @@ -620,13 +666,13 @@ em_reset_hw(struct em_hw *hw) } /* Disable HW ARPs on ASF enabled adapters */ - if(hw->mac_type >= em_82540 && hw->mac_type <= em_82547_rev_2) { + if (hw->mac_type >= em_82540 && hw->mac_type <= em_82547_rev_2) { manc = E1000_READ_REG(hw, MANC); manc &= ~(E1000_MANC_ARP_EN); E1000_WRITE_REG(hw, MANC, manc); } - if((hw->mac_type == em_82541) || (hw->mac_type == em_82547)) { + if ((hw->mac_type == em_82541) || (hw->mac_type == em_82547)) { em_phy_init_script(hw); /* Configure activity LED after PHY reset */ @@ -644,11 +690,17 @@ em_reset_hw(struct em_hw *hw) icr = E1000_READ_REG(hw, ICR); /* If MWI was previously enabled, reenable it. */ - if(hw->mac_type == em_82542_rev2_0) { - if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) + if (hw->mac_type == em_82542_rev2_0) { + if (hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) em_pci_set_mwi(hw); } + if (hw->mac_type == em_ich8lan) { + uint32_t kab = E1000_READ_REG(hw, KABGTXD); + kab |= E1000_KABGTXD_BGSQLBIAS; + E1000_WRITE_REG(hw, KABGTXD, kab); + } + return E1000_SUCCESS; } @@ -681,7 +733,7 @@ em_init_hw(struct em_hw *hw) /* Initialize Identification LED */ ret_val = em_id_led_init(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error Initializing Identification LED\n"); return ret_val; } @@ -691,12 +743,15 @@ em_init_hw(struct em_hw *hw) /* Disabling VLAN filtering. */ DEBUGOUT("Initializing the IEEE VLAN\n"); - if (hw->mac_type < em_82545_rev_3) - E1000_WRITE_REG(hw, VET, 0); - em_clear_vfta(hw); + /* VET hardcoded to standard value and VFTA removed in ICH8 LAN */ + if (hw->mac_type != em_ich8lan) { + if (hw->mac_type < em_82545_rev_3) + E1000_WRITE_REG(hw, VET, 0); + em_clear_vfta(hw); + } /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ - if(hw->mac_type == em_82542_rev2_0) { + if (hw->mac_type == em_82542_rev2_0) { DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); em_pci_clear_mwi(hw); E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST); @@ -710,37 +765,43 @@ em_init_hw(struct em_hw *hw) em_init_rx_addrs(hw); /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */ - if(hw->mac_type == em_82542_rev2_0) { + if (hw->mac_type == em_82542_rev2_0) { E1000_WRITE_REG(hw, RCTL, 0); E1000_WRITE_FLUSH(hw); msec_delay(1); - if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) + if (hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) em_pci_set_mwi(hw); } /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); mta_size = E1000_MC_TBL_SIZE; - for(i = 0; i < mta_size; i++) + if (hw->mac_type == em_ich8lan) + mta_size = E1000_MC_TBL_SIZE_ICH8LAN; + for (i = 0; i < mta_size; i++) { E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); + /* use write flush to prevent Memory Write Block (MWB) from + * occuring when accessing our register space */ + E1000_WRITE_FLUSH(hw); + } /* Set the PCI priority bit correctly in the CTRL register. This * determines if the adapter gives priority to receives, or if it * gives equal priority to transmits and receives. Valid only on * 82542 and 82543 silicon. */ - if(hw->dma_fairness && hw->mac_type <= em_82543) { + if (hw->dma_fairness && hw->mac_type <= em_82543) { ctrl = E1000_READ_REG(hw, CTRL); E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR); } - switch(hw->mac_type) { + switch (hw->mac_type) { case em_82545_rev_3: case em_82546_rev_3: break; default: /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ - if(hw->bus_type == em_bus_type_pcix) { + if (hw->bus_type == em_bus_type_pcix) { em_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); em_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word); @@ -748,9 +809,9 @@ em_init_hw(struct em_hw *hw) PCIX_COMMAND_MMRBC_SHIFT; stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> PCIX_STATUS_HI_MMRBC_SHIFT; - if(stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) + if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K; - if(cmd_mmrbc > stat_mmrbc) { + if (cmd_mmrbc > stat_mmrbc) { pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; em_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, @@ -760,11 +821,15 @@ em_init_hw(struct em_hw *hw) break; } + /* More time needed for PHY to initialize */ + if (hw->mac_type == em_ich8lan) + msec_delay(15); + /* Call a subroutine to configure the link and setup flow control. */ ret_val = em_setup_link(hw); /* Set the transmit descriptor write-back policy */ - if(hw->mac_type > em_82544) { + if (hw->mac_type > em_82544) { ctrl = E1000_READ_REG(hw, TXDCTL); ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; switch (hw->mac_type) { @@ -773,6 +838,7 @@ em_init_hw(struct em_hw *hw) case em_82571: case em_82572: case em_82573: + case em_ich8lan: case em_80003es2lan: ctrl |= E1000_TXDCTL_COUNT_DESC; break; @@ -781,7 +847,7 @@ em_init_hw(struct em_hw *hw) } if (hw->mac_type == em_82573) { - em_enable_tx_pkt_filtering(hw); + em_enable_tx_pkt_filtering(hw); } switch (hw->mac_type) { @@ -811,9 +877,10 @@ em_init_hw(struct em_hw *hw) /* FALLTHROUGH */ case em_82571: case em_82572: + case em_ich8lan: ctrl = E1000_READ_REG(hw, TXDCTL1); ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; - if(hw->mac_type >= em_82571) + if (hw->mac_type >= em_82571) ctrl |= E1000_TXDCTL_COUNT_DESC; E1000_WRITE_REG(hw, TXDCTL1, ctrl); break; @@ -832,6 +899,11 @@ em_init_hw(struct em_hw *hw) */ em_clear_hw_cntrs(hw); + /* ICH8/Nahum No-snoop bits are opposite polarity. + * Set to snoop by default after reset. */ + if (hw->mac_type == em_ich8lan) + em_set_pci_ex_no_snoop(hw, PCI_EX_82566_SNOOP_ALL); + if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER || hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) { ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); @@ -857,10 +929,10 @@ em_adjust_serdes_amplitude(struct em_hw *hw) DEBUGFUNC("em_adjust_serdes_amplitude"); - if(hw->media_type != em_media_type_internal_serdes) + if (hw->media_type != em_media_type_internal_serdes) return E1000_SUCCESS; - switch(hw->mac_type) { + switch (hw->mac_type) { case em_82545_rev_3: case em_82546_rev_3: break; @@ -873,11 +945,11 @@ em_adjust_serdes_amplitude(struct em_hw *hw) return ret_val; } - if(eeprom_data != EEPROM_RESERVED_WORD) { + if (eeprom_data != EEPROM_RESERVED_WORD) { /* Adjust SERDES output amplitude only. */ - eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; + eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; ret_val = em_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data); - if(ret_val) + if (ret_val) return ret_val; } @@ -919,6 +991,7 @@ em_setup_link(struct em_hw *hw) */ if (hw->fc == em_fc_default) { switch (hw->mac_type) { + case em_ich8lan: case em_82573: hw->fc = em_fc_full; break; @@ -944,10 +1017,10 @@ em_setup_link(struct em_hw *hw) * in case we get disconnected and then reconnected into a different * hub or switch with different Flow Control capabilities. */ - if(hw->mac_type == em_82542_rev2_0) + if (hw->mac_type == em_82542_rev2_0) hw->fc &= (~em_fc_tx_pause); - if((hw->mac_type < em_82543) && (hw->report_tx_early == 1)) + if ((hw->mac_type < em_82543) && (hw->report_tx_early == 1)) hw->fc &= (~em_fc_rx_pause); hw->original_fc = hw->fc; @@ -961,7 +1034,13 @@ em_setup_link(struct em_hw *hw) * signal detection. So this should be done before em_setup_pcs_link() * or em_phy_setup() is called. */ - if(hw->mac_type == em_82543) { + if (hw->mac_type == em_82543) { + ret_val = em_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, + 1, &eeprom_data); + if (ret_val) { + DEBUGOUT("EEPROM Read Error\n"); + return -E1000_ERR_EEPROM; + } ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << SWDPIO__EXT_SHIFT); E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); @@ -979,9 +1058,12 @@ em_setup_link(struct em_hw *hw) */ DEBUGOUT("Initializing the Flow Control address, type and timer regs\n"); - E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW); - E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH); - E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE); + /* FCAL/H and FCT are hardcoded to standard values in em_ich8lan. */ + if (hw->mac_type != em_ich8lan) { + E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE); + E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH); + E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW); + } E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time); @@ -991,14 +1073,14 @@ em_setup_link(struct em_hw *hw) * ability to transmit pause frames in not enabled, then these * registers will be set to 0. */ - if(!(hw->fc & em_fc_tx_pause)) { + if (!(hw->fc & em_fc_tx_pause)) { E1000_WRITE_REG(hw, FCRTL, 0); E1000_WRITE_REG(hw, FCRTH, 0); } else { /* We need to set up the Receive Threshold high and low water marks * as well as (optionally) enabling the transmission of XON frames. */ - if(hw->fc_send_xon) { + if (hw->fc_send_xon) { E1000_WRITE_REG(hw, FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE)); E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water); } else { @@ -1045,11 +1127,11 @@ em_setup_fiber_serdes_link(struct em_hw *hw) * the EEPROM. */ ctrl = E1000_READ_REG(hw, CTRL); - if(hw->media_type == em_media_type_fiber) + if (hw->media_type == em_media_type_fiber) signal = (hw->mac_type > em_82544) ? E1000_CTRL_SWDPIN1 : 0; ret_val = em_adjust_serdes_amplitude(hw); - if(ret_val) + if (ret_val) return ret_val; /* Take the link out of reset */ @@ -1057,7 +1139,7 @@ em_setup_fiber_serdes_link(struct em_hw *hw) /* Adjust VCO speed to improve BER performance */ ret_val = em_set_vco_speed(hw); - if(ret_val) + if (ret_val) return ret_val; em_config_collision_dist(hw); @@ -1128,15 +1210,15 @@ em_setup_fiber_serdes_link(struct em_hw *hw) * less than 500 milliseconds even if the other end is doing it in SW). * For internal serdes, we just assume a signal is present, then poll. */ - if(hw->media_type == em_media_type_internal_serdes || + if (hw->media_type == em_media_type_internal_serdes || (E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { DEBUGOUT("Looking for Link\n"); - for(i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { + for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { msec_delay(10); status = E1000_READ_REG(hw, STATUS); - if(status & E1000_STATUS_LU) break; + if (status & E1000_STATUS_LU) break; } - if(i == (LINK_UP_TIMEOUT / 10)) { + if (i == (LINK_UP_TIMEOUT / 10)) { DEBUGOUT("Never got a valid link from auto-neg!!!\n"); hw->autoneg_failed = 1; /* AutoNeg failed to achieve a link, so we'll call @@ -1145,7 +1227,7 @@ em_setup_fiber_serdes_link(struct em_hw *hw) * non-autonegotiating link partners. */ ret_val = em_check_for_link(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error while checking for link\n"); return ret_val; } @@ -1179,7 +1261,7 @@ em_copper_link_preconfig(struct em_hw *hw) * the PHY speed and duplex configuration is. In addition, we need to * perform a hardware reset on the PHY to take it out of reset. */ - if(hw->mac_type > em_82543) { + if (hw->mac_type > em_82543) { ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, CTRL, ctrl); @@ -1187,13 +1269,13 @@ em_copper_link_preconfig(struct em_hw *hw) ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU); E1000_WRITE_REG(hw, CTRL, ctrl); ret_val = em_phy_hw_reset(hw); - if(ret_val) + if (ret_val) return ret_val; } /* Make sure we have a valid PHY */ ret_val = em_detect_gig_phy(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error, did not detect valid phy.\n"); return ret_val; } @@ -1201,19 +1283,19 @@ em_copper_link_preconfig(struct em_hw *hw) /* Set PHY to class A mode (if necessary) */ ret_val = em_set_phy_mode(hw); - if(ret_val) + if (ret_val) return ret_val; - if((hw->mac_type == em_82545_rev_3) || + if ((hw->mac_type == em_82545_rev_3) || (hw->mac_type == em_82546_rev_3)) { ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); phy_data |= 0x00000008; ret_val = em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); } - if(hw->mac_type <= em_82543 || - hw->mac_type == em_82541 || hw->mac_type == em_82547 || - hw->mac_type == em_82541_rev_2 || hw->mac_type == em_82547_rev_2) + if (hw->mac_type <= em_82543 || + hw->mac_type == em_82541 || hw->mac_type == em_82547 || + hw->mac_type == em_82541_rev_2 || hw->mac_type == em_82547_rev_2) hw->phy_reset_disable = FALSE; return E1000_SUCCESS; @@ -1236,21 +1318,22 @@ em_copper_link_igp_setup(struct em_hw *hw) if (hw->phy_reset_disable) return E1000_SUCCESS; - + ret_val = em_phy_reset(hw); if (ret_val) { DEBUGOUT("Error Resetting the PHY\n"); return ret_val; } - /* Wait 10ms for MAC to configure PHY from eeprom settings */ + /* Wait 15ms for MAC to configure PHY from eeprom settings */ msec_delay(15); - + if (hw->mac_type != em_ich8lan) { /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); E1000_WRITE_REG(hw, LEDCTL, led_ctrl); + } /* disable lplu d3 during driver init */ ret_val = em_set_d3_lplu_state(hw, FALSE); @@ -1294,45 +1377,45 @@ em_copper_link_igp_setup(struct em_hw *hw) } } ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); - if(ret_val) + if (ret_val) return ret_val; /* set auto-master slave resolution settings */ - if(hw->autoneg) { + if (hw->autoneg) { em_ms_type phy_ms_setting = hw->master_slave; - if(hw->ffe_config_state == em_ffe_config_active) + if (hw->ffe_config_state == em_ffe_config_active) hw->ffe_config_state = em_ffe_config_enabled; - if(hw->dsp_config_state == em_dsp_config_activated) + if (hw->dsp_config_state == em_dsp_config_activated) hw->dsp_config_state = em_dsp_config_enabled; /* when autonegotiation advertisement is only 1000Mbps then we * should disable SmartSpeed and enable Auto MasterSlave * resolution as hardware default. */ - if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { + if (hw->autoneg_advertised == ADVERTISE_1000_FULL) { /* Disable SmartSpeed */ - ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data); - if(ret_val) + ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + &phy_data); + if (ret_val) return ret_val; phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = em_write_phy_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - phy_data); - if(ret_val) + ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + phy_data); + if (ret_val) return ret_val; /* Set auto Master/Slave resolution process */ ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data &= ~CR_1000T_MS_ENABLE; ret_val = em_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); - if(ret_val) + if (ret_val) return ret_val; } ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; /* load defaults for future use */ @@ -1357,7 +1440,7 @@ em_copper_link_igp_setup(struct em_hw *hw) break; } ret_val = em_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); - if(ret_val) + if (ret_val) return ret_val; } @@ -1378,12 +1461,12 @@ em_copper_link_ggp_setup(struct em_hw *hw) DEBUGFUNC("em_copper_link_ggp_setup"); - if(!hw->phy_reset_disable) { - + if (!hw->phy_reset_disable) { + /* Enable CRS on TX for half-duplex operation. */ ret_val = em_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; @@ -1392,7 +1475,7 @@ em_copper_link_ggp_setup(struct em_hw *hw) ret_val = em_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data); - if(ret_val) + if (ret_val) return ret_val; /* Options: @@ -1403,7 +1486,7 @@ em_copper_link_ggp_setup(struct em_hw *hw) * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) */ ret_val = em_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK; @@ -1428,11 +1511,11 @@ em_copper_link_ggp_setup(struct em_hw *hw) * 1 - Enabled */ phy_data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE; - if(hw->disable_polarity_correction == 1) + if (hw->disable_polarity_correction == 1) phy_data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE; ret_val = em_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data); - if(ret_val) + if (ret_val) return ret_val; /* SW Reset the PHY so all changes take effect */ @@ -1487,11 +1570,10 @@ em_copper_link_ggp_setup(struct em_hw *hw) if (ret_val) return ret_val; - /* Disable Pass False Carrier on the PHY */ phy_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; - ret_val = em_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, phy_data); + if (ret_val) return ret_val; } @@ -1526,12 +1608,12 @@ em_copper_link_mgp_setup(struct em_hw *hw) DEBUGFUNC("em_copper_link_mgp_setup"); - if(hw->phy_reset_disable) + if (hw->phy_reset_disable) return E1000_SUCCESS; - + /* Enable CRS on TX. This must be set for half-duplex operation. */ ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; @@ -1568,35 +1650,47 @@ em_copper_link_mgp_setup(struct em_hw *hw) * 1 - Enabled */ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if(hw->disable_polarity_correction == 1) + if (hw->disable_polarity_correction == 1) phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - ret_val = em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if(ret_val) - return ret_val; - - /* Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - ret_val = em_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); - if(ret_val) + ret_val = em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if (ret_val) return ret_val; - phy_data |= M88E1000_EPSCR_TX_CLK_25; - if (hw->phy_revision < M88E1011_I_REV_4) { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | + /* Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ + ret_val = em_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + return ret_val; + + phy_data |= M88E1000_EPSCR_TX_CLK_25; + + if ((hw->phy_revision == E1000_REVISION_2) && + (hw->phy_id == M88E1111_I_PHY_ID)) { + /* Vidalia Phy, set the downshift counter to 5x */ + phy_data &= ~(M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK); + phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; + ret_val = em_write_phy_reg(hw, + M88E1000_EXT_PHY_SPEC_CTRL, phy_data); + if (ret_val) + return ret_val; + } else { + /* Configure Master and Slave downshift values */ + phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | + phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - ret_val = em_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); - if(ret_val) - return ret_val; + ret_val = em_write_phy_reg(hw, + M88E1000_EXT_PHY_SPEC_CTRL, phy_data); + if (ret_val) + return ret_val; + } } /* SW Reset the PHY so all changes take effect */ ret_val = em_phy_reset(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error Resetting the PHY\n"); return ret_val; } @@ -1626,12 +1720,16 @@ em_copper_link_autoneg(struct em_hw *hw) /* If autoneg_advertised is zero, we assume it was not defaulted * by the calling code so we set to advertise full capability. */ - if(hw->autoneg_advertised == 0) + if (hw->autoneg_advertised == 0) hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; + /* IFE phy only supports 10/100 */ + if (hw->phy_type == em_phy_ife) + hw->autoneg_advertised &= AUTONEG_ADVERTISE_10_100_ALL; + DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); ret_val = em_phy_setup_autoneg(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error Setting up Auto-Negotiation\n"); return ret_val; } @@ -1641,20 +1739,20 @@ em_copper_link_autoneg(struct em_hw *hw) * the Auto Neg Restart bit in the PHY control register. */ ret_val = em_read_phy_reg(hw, PHY_CTRL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); ret_val = em_write_phy_reg(hw, PHY_CTRL, phy_data); - if(ret_val) + if (ret_val) return ret_val; /* Does the user want to wait for Auto-Neg to complete here, or * check at a later time (for example, callback routine). */ - if(hw->wait_autoneg_complete) { + if (hw->wait_autoneg_complete) { ret_val = em_wait_autoneg(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error while waiting for autoneg to complete\n"); return ret_val; } @@ -1665,6 +1763,18 @@ em_copper_link_autoneg(struct em_hw *hw) return E1000_SUCCESS; } +/******************************************************************** +* Copper link setup for em_phy_ife (Fast Ethernet PHY) series. +* +* hw - Struct containing variables accessed by shared code +*********************************************************************/ +static int32_t +em_copper_link_ife_setup(struct em_hw *hw) +{ + if (hw->phy_reset_disable) + return E1000_SUCCESS; + return E1000_SUCCESS; +} /****************************************************************************** * Config the MAC and the PHY after link is up. @@ -1674,7 +1784,7 @@ em_copper_link_autoneg(struct em_hw *hw) * collision distance in the Transmit Control Register. * 2) Set up flow control on the MAC to that established with * the link partner. -* 3) Config DSP to improve Gigabit link quality for some PHY revisions. +* 3) Config DSP to improve Gigabit link quality for some PHY revisions. * * hw - Struct containing variables accessed by shared code ******************************************************************************/ @@ -1683,31 +1793,31 @@ em_copper_link_postconfig(struct em_hw *hw) { int32_t ret_val; DEBUGFUNC("em_copper_link_postconfig"); - - if(hw->mac_type >= em_82544) { + + if (hw->mac_type >= em_82544) { em_config_collision_dist(hw); } else { ret_val = em_config_mac_to_phy(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error configuring MAC to PHY settings\n"); return ret_val; } } ret_val = em_config_fc_after_link_up(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error Configuring Flow Control\n"); return ret_val; } /* Config DSP to improve Giga link quality */ - if(hw->phy_type == em_phy_igp) { + if (hw->phy_type == em_phy_igp) { ret_val = em_config_dsp_after_link_change(hw, TRUE); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error Configuring DSP after link up\n"); return ret_val; } } - + return E1000_SUCCESS; } @@ -1728,6 +1838,7 @@ em_setup_copper_link(struct em_hw *hw) switch (hw->mac_type) { case em_80003es2lan: + case em_ich8lan: /* Set the mac to wait the maximum time between each * iteration and increase the max iterations when * polling the phy; this fixes erroneous timeouts at 10Mbps. */ @@ -1747,15 +1858,13 @@ em_setup_copper_link(struct em_hw *hw) /* Check if it is a valid PHY and set PHY mode if necessary. */ ret_val = em_copper_link_preconfig(hw); - if(ret_val) + if (ret_val) return ret_val; switch (hw->mac_type) { case em_80003es2lan: - ret_val = em_read_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL, - ®_data); - if (ret_val) - return ret_val; + /* Kumeran registers are written-only */ + reg_data = E1000_KUMCTRLSTA_INB_CTRL_LINK_STATUS_TX_TIMEOUT_DEFAULT; reg_data |= E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING; ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL, reg_data); @@ -1767,32 +1876,37 @@ em_setup_copper_link(struct em_hw *hw) } if (hw->phy_type == em_phy_igp || + hw->phy_type == em_phy_igp_3 || hw->phy_type == em_phy_igp_2) { ret_val = em_copper_link_igp_setup(hw); - if(ret_val) + if (ret_val) return ret_val; } else if (hw->phy_type == em_phy_m88) { ret_val = em_copper_link_mgp_setup(hw); - if(ret_val) + if (ret_val) return ret_val; } else if (hw->phy_type == em_phy_gg82563) { ret_val = em_copper_link_ggp_setup(hw); - if(ret_val) + if (ret_val) + return ret_val; + } else if (hw->phy_type == em_phy_ife) { + ret_val = em_copper_link_ife_setup(hw); + if (ret_val) return ret_val; } - if(hw->autoneg) { - /* Setup autoneg and flow control advertisement - * and perform autonegotiation */ + if (hw->autoneg) { + /* Setup autoneg and flow control advertisement + * and perform autonegotiation */ ret_val = em_copper_link_autoneg(hw); - if(ret_val) - return ret_val; + if (ret_val) + return ret_val; } else { /* PHY will be set to 10H, 10F, 100H,or 100F * depending on value from forced_speed_duplex. */ DEBUGOUT("Forcing speed and duplex\n"); ret_val = em_phy_force_speed_duplex(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error Forcing Speed and Duplex\n"); return ret_val; } @@ -1801,20 +1915,20 @@ em_setup_copper_link(struct em_hw *hw) /* Check link status. Wait up to 100 microseconds for link to become * valid. */ - for(i = 0; i < 10; i++) { + for (i = 0; i < 10; i++) { ret_val = em_read_phy_reg(hw, PHY_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_read_phy_reg(hw, PHY_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; - if(phy_data & MII_SR_LINK_STATUS) { + if (phy_data & MII_SR_LINK_STATUS) { /* Config the MAC and PHY after link is up */ ret_val = em_copper_link_postconfig(hw); - if(ret_val) + if (ret_val) return ret_val; - + DEBUGOUT("Valid link established!!!\n"); return E1000_SUCCESS; } @@ -1851,26 +1965,23 @@ em_configure_kmrn_for_10_100(struct em_hw *hw, uint16_t duplex) tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_10_100; E1000_WRITE_REG(hw, TIPG, tipg); - ret_val = em_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, - ®_data); + ret_val = em_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); + if (ret_val) return ret_val; - /* Enable pass false carrier when in half duplex mode. */ if (duplex == HALF_DUPLEX) reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER; else reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; + ret_val = em_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); - ret_val = em_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, - reg_data); - return ret_val; } static int32_t -em_configure_kmrn_for_1000(struct em_hw *hw, uint16_t duplex) +em_configure_kmrn_for_1000(struct em_hw *hw) { int32_t ret_val = E1000_SUCCESS; uint16_t reg_data; @@ -1890,18 +2001,14 @@ em_configure_kmrn_for_1000(struct em_hw *hw, uint16_t duplex) tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000; E1000_WRITE_REG(hw, TIPG, tipg); + ret_val = em_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); - ret_val = em_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, - ®_data); if (ret_val) return ret_val; - /* Disable Pass False Carrier on the PHY */ reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; + ret_val = em_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); - ret_val = em_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, - reg_data); - return ret_val; } @@ -1921,13 +2028,16 @@ em_phy_setup_autoneg(struct em_hw *hw) /* Read the MII Auto-Neg Advertisement Register (Address 4). */ ret_val = em_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); - if(ret_val) + if (ret_val) return ret_val; - /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); - if(ret_val) - return ret_val; + if (hw->phy_type != em_phy_ife) { + /* Read the MII 1000Base-T Control Register (Address 9). */ + ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); + if (ret_val) + return ret_val; + } else + mii_1000t_ctrl_reg=0; /* Need to parse both autoneg_advertised and fc and set up * the appropriate PHY registers. First we will parse for @@ -1946,38 +2056,41 @@ em_phy_setup_autoneg(struct em_hw *hw) DEBUGOUT1("autoneg_advertised %x\n", hw->autoneg_advertised); /* Do we want to advertise 10 Mb Half Duplex? */ - if(hw->autoneg_advertised & ADVERTISE_10_HALF) { + if (hw->autoneg_advertised & ADVERTISE_10_HALF) { DEBUGOUT("Advertise 10mb Half duplex\n"); mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; } /* Do we want to advertise 10 Mb Full Duplex? */ - if(hw->autoneg_advertised & ADVERTISE_10_FULL) { + if (hw->autoneg_advertised & ADVERTISE_10_FULL) { DEBUGOUT("Advertise 10mb Full duplex\n"); mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; } /* Do we want to advertise 100 Mb Half Duplex? */ - if(hw->autoneg_advertised & ADVERTISE_100_HALF) { + if (hw->autoneg_advertised & ADVERTISE_100_HALF) { DEBUGOUT("Advertise 100mb Half duplex\n"); mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; } /* Do we want to advertise 100 Mb Full Duplex? */ - if(hw->autoneg_advertised & ADVERTISE_100_FULL) { + if (hw->autoneg_advertised & ADVERTISE_100_FULL) { DEBUGOUT("Advertise 100mb Full duplex\n"); mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; } /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ - if(hw->autoneg_advertised & ADVERTISE_1000_HALF) { + if (hw->autoneg_advertised & ADVERTISE_1000_HALF) { DEBUGOUT("Advertise 1000mb Half duplex requested, request denied!\n"); } /* Do we want to advertise 1000 Mb Full Duplex? */ - if(hw->autoneg_advertised & ADVERTISE_1000_FULL) { + if (hw->autoneg_advertised & ADVERTISE_1000_FULL) { DEBUGOUT("Advertise 1000mb Full duplex\n"); mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; + if (hw->phy_type == em_phy_ife) { + DEBUGOUT("em_phy_ife is a 10/100 PHY. Gigabit speed is not supported.\n"); + } } /* Check for a software override of the flow control settings, and @@ -2034,14 +2147,16 @@ em_phy_setup_autoneg(struct em_hw *hw) } ret_val = em_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); - if(ret_val) + if (ret_val) return ret_val; DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - ret_val = em_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg); - if(ret_val) - return ret_val; + if (hw->phy_type != em_phy_ife) { + ret_val = em_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg); + if (ret_val) + return ret_val; + } return E1000_SUCCESS; } @@ -2080,7 +2195,7 @@ em_phy_force_speed_duplex(struct em_hw *hw) /* Read the MII Control Register. */ ret_val = em_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg); - if(ret_val) + if (ret_val) return ret_val; /* We need to disable autoneg in order to force link and duplex. */ @@ -2088,8 +2203,8 @@ em_phy_force_speed_duplex(struct em_hw *hw) mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN; /* Are we forcing Full or Half Duplex? */ - if(hw->forced_speed_duplex == em_100_full || - hw->forced_speed_duplex == em_10_full) { + if (hw->forced_speed_duplex == em_100_full || + hw->forced_speed_duplex == em_10_full) { /* We want to force full duplex so we SET the full duplex bits in the * Device and MII Control Registers. */ @@ -2106,7 +2221,7 @@ em_phy_force_speed_duplex(struct em_hw *hw) } /* Are we forcing 100Mbps??? */ - if(hw->forced_speed_duplex == em_100_full || + if (hw->forced_speed_duplex == em_100_full || hw->forced_speed_duplex == em_100_half) { /* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */ ctrl |= E1000_CTRL_SPD_100; @@ -2129,7 +2244,7 @@ em_phy_force_speed_duplex(struct em_hw *hw) if ((hw->phy_type == em_phy_m88) || (hw->phy_type == em_phy_gg82563)) { ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI @@ -2137,32 +2252,44 @@ em_phy_force_speed_duplex(struct em_hw *hw) */ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; ret_val = em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if(ret_val) + if (ret_val) return ret_val; DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data); /* Need to reset the PHY or these changes will be ignored */ mii_ctrl_reg |= MII_CR_RESET; + /* Disable MDI-X support for 10/100 */ + } else if (hw->phy_type == em_phy_ife) { + ret_val = em_read_phy_reg(hw, IFE_PHY_MDIX_CONTROL, &phy_data); + if (ret_val) + return ret_val; + + phy_data &= ~IFE_PMC_AUTO_MDIX; + phy_data &= ~IFE_PMC_FORCE_MDIX; + + ret_val = em_write_phy_reg(hw, IFE_PHY_MDIX_CONTROL, phy_data); + if (ret_val) + return ret_val; } else { /* Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed or duplex are forced. */ ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); - if(ret_val) + if (ret_val) return ret_val; } /* Write back the modified PHY MII control register. */ ret_val = em_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg); - if(ret_val) + if (ret_val) return ret_val; usec_delay(1); @@ -2174,50 +2301,50 @@ em_phy_force_speed_duplex(struct em_hw *hw) * only if the user has set wait_autoneg_complete to 1, which is * the default. */ - if(hw->wait_autoneg_complete) { + if (hw->wait_autoneg_complete) { /* We will wait for autoneg to complete. */ DEBUGOUT("Waiting for forced speed/duplex link.\n"); mii_status_reg = 0; /* We will wait for autoneg to complete or 4.5 seconds to expire. */ - for(i = PHY_FORCE_TIME; i > 0; i--) { + for (i = PHY_FORCE_TIME; i > 0; i--) { /* Read the MII Status Register and wait for Auto-Neg Complete bit * to be set. */ ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if(ret_val) + if (ret_val) return ret_val; - if(mii_status_reg & MII_SR_LINK_STATUS) break; + if (mii_status_reg & MII_SR_LINK_STATUS) break; msec_delay(100); } - if((i == 0) && + if ((i == 0) && ((hw->phy_type == em_phy_m88) || (hw->phy_type == em_phy_gg82563))) { /* We didn't get link. Reset the DSP and wait again for link. */ ret_val = em_phy_reset_dsp(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error Resetting PHY DSP\n"); return ret_val; } } /* This loop will early-out if the link condition has been met. */ - for(i = PHY_FORCE_TIME; i > 0; i--) { - if(mii_status_reg & MII_SR_LINK_STATUS) break; + for (i = PHY_FORCE_TIME; i > 0; i--) { + if (mii_status_reg & MII_SR_LINK_STATUS) break; msec_delay(100); /* Read the MII Status Register and wait for Auto-Neg Complete bit * to be set. */ ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if(ret_val) + if (ret_val) return ret_val; } } @@ -2228,32 +2355,31 @@ em_phy_force_speed_duplex(struct em_hw *hw) * defaults back to a 2.5MHz clock when the PHY is reset. */ ret_val = em_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data |= M88E1000_EPSCR_TX_CLK_25; ret_val = em_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); - if(ret_val) + if (ret_val) return ret_val; /* In addition, because of the s/w reset above, we need to enable CRS on * TX. This must be set for both full and half duplex operation. */ ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; ret_val = em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if(ret_val) + if (ret_val) return ret_val; - if((hw->mac_type == em_82544 || hw->mac_type == em_82543) && - (!hw->autoneg) && - (hw->forced_speed_duplex == em_10_full || - hw->forced_speed_duplex == em_10_half)) { + if ((hw->mac_type == em_82544 || hw->mac_type == em_82543) && + (!hw->autoneg) && (hw->forced_speed_duplex == em_10_full || + hw->forced_speed_duplex == em_10_half)) { ret_val = em_polarity_reversal_workaround(hw); - if(ret_val) + if (ret_val) return ret_val; } } else if (hw->phy_type == em_phy_gg82563) { @@ -2328,7 +2454,7 @@ em_config_mac_to_phy(struct em_hw *hw) DEBUGFUNC("em_config_mac_to_phy"); - /* 82544 or newer MAC, Auto Speed Detection takes care of + /* 82544 or newer MAC, Auto Speed Detection takes care of * MAC speed/duplex configuration.*/ if (hw->mac_type >= em_82544) return E1000_SUCCESS; @@ -2344,12 +2470,12 @@ em_config_mac_to_phy(struct em_hw *hw) * registers depending on negotiated values. */ ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; - if(phy_data & M88E1000_PSSR_DPLX) + if (phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD; - else + else ctrl &= ~E1000_CTRL_FD; em_config_collision_dist(hw); @@ -2357,9 +2483,9 @@ em_config_mac_to_phy(struct em_hw *hw) /* Set up speed in the Device Control register depending on * negotiated values. */ - if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) + if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) ctrl |= E1000_CTRL_SPD_1000; - else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) + else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) ctrl |= E1000_CTRL_SPD_100; /* Write the configured values back to the Device Control Reg. */ @@ -2427,7 +2553,7 @@ em_force_mac_fc(struct em_hw *hw) } /* Disable TX Flow Control for 82542 (rev 2.0) */ - if(hw->mac_type == em_82542_rev2_0) + if (hw->mac_type == em_82542_rev2_0) ctrl &= (~E1000_CTRL_TFCE); E1000_WRITE_REG(hw, CTRL, ctrl); @@ -2461,11 +2587,12 @@ em_config_fc_after_link_up(struct em_hw *hw) * so we had to force link. In this case, we need to force the * configuration of the MAC to match the "fc" parameter. */ - if(((hw->media_type == em_media_type_fiber) && (hw->autoneg_failed)) || - ((hw->media_type == em_media_type_internal_serdes) && (hw->autoneg_failed)) || - ((hw->media_type == em_media_type_copper) && (!hw->autoneg))) { + if (((hw->media_type == em_media_type_fiber) && (hw->autoneg_failed)) || + ((hw->media_type == em_media_type_internal_serdes) && + (hw->autoneg_failed)) || + ((hw->media_type == em_media_type_copper) && (!hw->autoneg))) { ret_val = em_force_mac_fc(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; } @@ -2476,19 +2603,19 @@ em_config_fc_after_link_up(struct em_hw *hw) * has completed, and if so, how the PHY and link partner has * flow control configured. */ - if((hw->media_type == em_media_type_copper) && hw->autoneg) { + if ((hw->media_type == em_media_type_copper) && hw->autoneg) { /* Read the MII Status Register and check to see if AutoNeg * has completed. We read this twice because this reg has * some "sticky" (latched) bits. */ ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if(ret_val) + if (ret_val) return ret_val; - if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) { + if (mii_status_reg & MII_SR_AUTONEG_COMPLETE) { /* The AutoNeg process has completed, so we now need to * read both the Auto Negotiation Advertisement Register * (Address 4) and the Auto_Negotiation Base Page Ability @@ -2497,11 +2624,11 @@ em_config_fc_after_link_up(struct em_hw *hw) */ ret_val = em_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_read_phy_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg); - if(ret_val) + if (ret_val) return ret_val; /* Two bits in the Auto Negotiation Advertisement Register @@ -2538,15 +2665,15 @@ em_config_fc_after_link_up(struct em_hw *hw) * 1 | DC | 1 | DC | em_fc_full * */ - if((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { + if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { /* Now we need to check if the user selected RX ONLY * of pause frames. In this case, we had to advertise * FULL flow control because we could not advertise RX * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ - if(hw->original_fc == em_fc_full) { + if (hw->original_fc == em_fc_full) { hw->fc = em_fc_full; DEBUGOUT("Flow Control = FULL.\n"); } else { @@ -2562,10 +2689,10 @@ em_config_fc_after_link_up(struct em_hw *hw) * 0 | 1 | 1 | 1 | em_fc_tx_pause * */ - else if(!(mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { + else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && + (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc = em_fc_tx_pause; DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); } @@ -2577,10 +2704,10 @@ em_config_fc_after_link_up(struct em_hw *hw) * 1 | 1 | 0 | 1 | em_fc_rx_pause * */ - else if((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { + else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && + !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc = em_fc_rx_pause; DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } @@ -2604,9 +2731,9 @@ em_config_fc_after_link_up(struct em_hw *hw) * be asked to delay transmission of packets than asking * our link partner to pause transmission of frames. */ - else if((hw->original_fc == em_fc_none || - hw->original_fc == em_fc_tx_pause) || - hw->fc_strict_ieee) { + else if ((hw->original_fc == em_fc_none || + hw->original_fc == em_fc_tx_pause) || + hw->fc_strict_ieee) { hw->fc = em_fc_none; DEBUGOUT("Flow Control = NONE.\n"); } else { @@ -2619,19 +2746,19 @@ em_config_fc_after_link_up(struct em_hw *hw) * enabled per IEEE 802.3 spec. */ ret_val = em_get_speed_and_duplex(hw, &speed, &duplex); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error getting link speed and duplex\n"); return ret_val; } - if(duplex == HALF_DUPLEX) + if (duplex == HALF_DUPLEX) hw->fc = em_fc_none; /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. */ ret_val = em_force_mac_fc(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; } @@ -2670,13 +2797,13 @@ em_check_for_link(struct em_hw *hw) * set when the optics detect a signal. On older adapters, it will be * cleared when there is a signal. This applies to fiber media only. */ - if((hw->media_type == em_media_type_fiber) || - (hw->media_type == em_media_type_internal_serdes)) { + if ((hw->media_type == em_media_type_fiber) || + (hw->media_type == em_media_type_internal_serdes)) { rxcw = E1000_READ_REG(hw, RXCW); - if(hw->media_type == em_media_type_fiber) { + if (hw->media_type == em_media_type_fiber) { signal = (hw->mac_type > em_82544) ? E1000_CTRL_SWDPIN1 : 0; - if(status & E1000_STATUS_LU) + if (status & E1000_STATUS_LU) hw->get_link_status = FALSE; } } @@ -2687,20 +2814,20 @@ em_check_for_link(struct em_hw *hw) * receive a Link Status Change interrupt or we have Rx Sequence * Errors. */ - if((hw->media_type == em_media_type_copper) && hw->get_link_status) { + if ((hw->media_type == em_media_type_copper) && hw->get_link_status) { /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex * of the PHY. * Read the register twice since the link bit is sticky. */ ret_val = em_read_phy_reg(hw, PHY_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_read_phy_reg(hw, PHY_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; - if(phy_data & MII_SR_LINK_STATUS) { + if (phy_data & MII_SR_LINK_STATUS) { hw->get_link_status = FALSE; /* Check if there was DownShift, must be checked immediately after * link-up */ @@ -2714,10 +2841,10 @@ em_check_for_link(struct em_hw *hw) * happen due to the execution of this workaround. */ - if((hw->mac_type == em_82544 || hw->mac_type == em_82543) && - (!hw->autoneg) && - (hw->forced_speed_duplex == em_10_full || - hw->forced_speed_duplex == em_10_half)) { + if ((hw->mac_type == em_82544 || hw->mac_type == em_82543) && + (!hw->autoneg) && + (hw->forced_speed_duplex == em_10_full || + hw->forced_speed_duplex == em_10_half)) { E1000_WRITE_REG(hw, IMC, 0xffffffff); ret_val = em_polarity_reversal_workaround(hw); icr = E1000_READ_REG(hw, ICR); @@ -2734,7 +2861,7 @@ em_check_for_link(struct em_hw *hw) /* If we are forcing speed/duplex, then we simply return since * we have already determined whether we have link or not. */ - if(!hw->autoneg) return -E1000_ERR_CONFIG; + if (!hw->autoneg) return -E1000_ERR_CONFIG; /* optimize the dsp settings for the igp phy */ em_config_dsp_after_link_change(hw, TRUE); @@ -2747,11 +2874,11 @@ em_check_for_link(struct em_hw *hw) * speed/duplex on the MAC to the current PHY speed/duplex * settings. */ - if(hw->mac_type >= em_82544) + if (hw->mac_type >= em_82544) em_config_collision_dist(hw); else { ret_val = em_config_mac_to_phy(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error configuring MAC to PHY settings\n"); return ret_val; } @@ -2762,7 +2889,7 @@ em_check_for_link(struct em_hw *hw) * have had to re-autoneg with a different link partner. */ ret_val = em_config_fc_after_link_up(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } @@ -2774,14 +2901,18 @@ em_check_for_link(struct em_hw *hw) * at gigabit speed, then TBI compatibility is not needed. If we are * at gigabit speed, we turn on TBI compatibility. */ - if(hw->tbi_compatibility_en) { + if (hw->tbi_compatibility_en) { uint16_t speed, duplex; - em_get_speed_and_duplex(hw, &speed, &duplex); - if(speed != SPEED_1000) { + ret_val = em_get_speed_and_duplex(hw, &speed, &duplex); + if (ret_val) { + DEBUGOUT("Error getting link speed and duplex\n"); + return ret_val; + } + if (speed != SPEED_1000) { /* If link speed is not set to gigabit speed, we do not need * to enable TBI compatibility. */ - if(hw->tbi_compatibility_on) { + if (hw->tbi_compatibility_on) { /* If we previously were in the mode, turn it off. */ rctl = E1000_READ_REG(hw, RCTL); rctl &= ~E1000_RCTL_SBP; @@ -2794,7 +2925,7 @@ em_check_for_link(struct em_hw *hw) * packets. Some frames have an additional byte on the end and * will look like CRC errors to to the hardware. */ - if(!hw->tbi_compatibility_on) { + if (!hw->tbi_compatibility_on) { hw->tbi_compatibility_on = TRUE; rctl = E1000_READ_REG(hw, RCTL); rctl |= E1000_RCTL_SBP; @@ -2810,12 +2941,12 @@ em_check_for_link(struct em_hw *hw) * auto-negotiation time to complete, in case the cable was just plugged * in. The autoneg_failed flag does this. */ - else if((((hw->media_type == em_media_type_fiber) && + else if ((((hw->media_type == em_media_type_fiber) && ((ctrl & E1000_CTRL_SWDPIN1) == signal)) || - (hw->media_type == em_media_type_internal_serdes)) && - (!(status & E1000_STATUS_LU)) && - (!(rxcw & E1000_RXCW_C))) { - if(hw->autoneg_failed == 0) { + (hw->media_type == em_media_type_internal_serdes)) && + (!(status & E1000_STATUS_LU)) && + (!(rxcw & E1000_RXCW_C))) { + if (hw->autoneg_failed == 0) { hw->autoneg_failed = 1; return 0; } @@ -2831,7 +2962,7 @@ em_check_for_link(struct em_hw *hw) /* Configure Flow Control after forcing link up. */ ret_val = em_config_fc_after_link_up(hw); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } @@ -2841,9 +2972,9 @@ em_check_for_link(struct em_hw *hw) * Device Control register in an attempt to auto-negotiate with our link * partner. */ - else if(((hw->media_type == em_media_type_fiber) || - (hw->media_type == em_media_type_internal_serdes)) && - (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { + else if (((hw->media_type == em_media_type_fiber) || + (hw->media_type == em_media_type_internal_serdes)) && + (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); E1000_WRITE_REG(hw, TXCW, hw->txcw); E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU)); @@ -2853,12 +2984,12 @@ em_check_for_link(struct em_hw *hw) /* If we force link for non-auto-negotiation switch, check link status * based on MAC synchronization for internal serdes media type. */ - else if((hw->media_type == em_media_type_internal_serdes) && - !(E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) { + else if ((hw->media_type == em_media_type_internal_serdes) && + !(E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) { /* SYNCH bit and IV bit are sticky. */ usec_delay(10); - if(E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) { - if(!(rxcw & E1000_RXCW_IV)) { + if (E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) { + if (!(rxcw & E1000_RXCW_IV)) { hw->serdes_link_down = FALSE; DEBUGOUT("SERDES: Link is up.\n"); } @@ -2867,8 +2998,8 @@ em_check_for_link(struct em_hw *hw) DEBUGOUT("SERDES: Link is down.\n"); } } - if((hw->media_type == em_media_type_internal_serdes) && - (E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) { + if ((hw->media_type == em_media_type_internal_serdes) && + (E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) { hw->serdes_link_down = !(E1000_STATUS_LU & E1000_READ_REG(hw, STATUS)); } return E1000_SUCCESS; @@ -2892,12 +3023,12 @@ em_get_speed_and_duplex(struct em_hw *hw, DEBUGFUNC("em_get_speed_and_duplex"); - if(hw->mac_type >= em_82543) { + if (hw->mac_type >= em_82543) { status = E1000_READ_REG(hw, STATUS); - if(status & E1000_STATUS_SPEED_1000) { + if (status & E1000_STATUS_SPEED_1000) { *speed = SPEED_1000; DEBUGOUT("1000 Mbs, "); - } else if(status & E1000_STATUS_SPEED_100) { + } else if (status & E1000_STATUS_SPEED_100) { *speed = SPEED_100; DEBUGOUT("100 Mbs, "); } else { @@ -2905,7 +3036,7 @@ em_get_speed_and_duplex(struct em_hw *hw, DEBUGOUT("10 Mbs, "); } - if(status & E1000_STATUS_FD) { + if (status & E1000_STATUS_FD) { *duplex = FULL_DUPLEX; DEBUGOUT("Full Duplex\n"); } else { @@ -2922,33 +3053,39 @@ em_get_speed_and_duplex(struct em_hw *hw, * if it is operating at half duplex. Here we set the duplex settings to * match the duplex in the link partner's capabilities. */ - if(hw->phy_type == em_phy_igp && hw->speed_downgraded) { + if (hw->phy_type == em_phy_igp && hw->speed_downgraded) { ret_val = em_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data); - if(ret_val) + if (ret_val) return ret_val; - if(!(phy_data & NWAY_ER_LP_NWAY_CAPS)) + if (!(phy_data & NWAY_ER_LP_NWAY_CAPS)) *duplex = HALF_DUPLEX; else { ret_val = em_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data); - if(ret_val) + if (ret_val) return ret_val; - if((*speed == SPEED_100 && !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) || + if ((*speed == SPEED_100 && !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) || (*speed == SPEED_10 && !(phy_data & NWAY_LPAR_10T_FD_CAPS))) *duplex = HALF_DUPLEX; } } - if ((hw->mac_type == em_80003es2lan) && + if ((hw->mac_type == em_80003es2lan) && (hw->media_type == em_media_type_copper)) { if (*speed == SPEED_1000) - ret_val = em_configure_kmrn_for_1000(hw, *duplex); + ret_val = em_configure_kmrn_for_1000(hw); else ret_val = em_configure_kmrn_for_10_100(hw, *duplex); if (ret_val) return ret_val; } + if ((hw->phy_type == em_phy_igp_3) && (*speed == SPEED_1000)) { + ret_val = em_kumeran_lock_loss_workaround(hw); + if (ret_val) + return ret_val; + } + return E1000_SUCCESS; } @@ -2968,17 +3105,17 @@ em_wait_autoneg(struct em_hw *hw) DEBUGOUT("Waiting for Auto-Neg to complete.\n"); /* We will wait for autoneg to complete or 4.5 seconds to expire. */ - for(i = PHY_AUTO_NEG_TIME; i > 0; i--) { + for (i = PHY_AUTO_NEG_TIME; i > 0; i--) { /* Read the MII Status Register and wait for Auto-Neg * Complete bit to be set. */ ret_val = em_read_phy_reg(hw, PHY_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_read_phy_reg(hw, PHY_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; - if(phy_data & MII_SR_AUTONEG_COMPLETE) { + if (phy_data & MII_SR_AUTONEG_COMPLETE) { return E1000_SUCCESS; } msec_delay(100); @@ -3051,14 +3188,16 @@ em_shift_out_mdi_bits(struct em_hw *hw, /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */ ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR); - while(mask) { + while (mask) { /* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and * then raising and lowering the Management Data Clock. A "0" is * shifted out to the PHY by setting the MDIO bit to "0" and then * raising and lowering the clock. */ - if(data & mask) ctrl |= E1000_CTRL_MDIO; - else ctrl &= ~E1000_CTRL_MDIO; + if (data & mask) + ctrl |= E1000_CTRL_MDIO; + else + ctrl &= ~E1000_CTRL_MDIO; E1000_WRITE_REG(hw, CTRL, ctrl); E1000_WRITE_FLUSH(hw); @@ -3109,12 +3248,13 @@ em_shift_in_mdi_bits(struct em_hw *hw) em_raise_mdi_clk(hw, &ctrl); em_lower_mdi_clk(hw, &ctrl); - for(data = 0, i = 0; i < 16; i++) { + for (data = 0, i = 0; i < 16; i++) { data = data << 1; em_raise_mdi_clk(hw, &ctrl); ctrl = E1000_READ_REG(hw, CTRL); /* Check to see if we shifted in a "1". */ - if(ctrl & E1000_CTRL_MDIO) data |= 1; + if (ctrl & E1000_CTRL_MDIO) + data |= 1; em_lower_mdi_clk(hw, &ctrl); } @@ -3134,10 +3274,13 @@ em_swfw_sync_acquire(struct em_hw *hw, uint16_t mask) DEBUGFUNC("em_swfw_sync_acquire"); + if (hw->swfwhw_semaphore_present) + return em_get_software_flag(hw); + if (!hw->swfw_sync_present) return em_get_hw_eeprom_semaphore(hw); - while(timeout) { + while (timeout) { if (em_get_hw_eeprom_semaphore(hw)) return -E1000_ERR_SWFW_SYNC; @@ -3173,6 +3316,11 @@ em_swfw_sync_release(struct em_hw *hw, uint16_t mask) DEBUGFUNC("em_swfw_sync_release"); + if (hw->swfwhw_semaphore_present) { + em_release_software_flag(hw); + return; + } + if (!hw->swfw_sync_present) { em_put_hw_eeprom_semaphore(hw); return; @@ -3215,12 +3363,13 @@ em_read_phy_reg(struct em_hw *hw, if (em_swfw_sync_acquire(hw, swfw)) return -E1000_ERR_SWFW_SYNC; - if((hw->phy_type == em_phy_igp || + if ((hw->phy_type == em_phy_igp || + hw->phy_type == em_phy_igp_3 || hw->phy_type == em_phy_igp_2) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { ret_val = em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, (uint16_t)reg_addr); - if(ret_val) { + if (ret_val) { em_swfw_sync_release(hw, swfw); return ret_val; } @@ -3265,12 +3414,12 @@ em_read_phy_reg_ex(struct em_hw *hw, DEBUGFUNC("em_read_phy_reg_ex"); - if(reg_addr > MAX_PHY_REG_ADDRESS) { + if (reg_addr > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", reg_addr); return -E1000_ERR_PARAM; } - if(hw->mac_type > em_82543) { + if (hw->mac_type > em_82543) { /* Set up Op-code, Phy Address, and register address in the MDI * Control register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. @@ -3282,16 +3431,16 @@ em_read_phy_reg_ex(struct em_hw *hw, E1000_WRITE_REG(hw, MDIC, mdic); /* Poll the ready bit to see if the MDI read completed */ - for(i = 0; i < 64; i++) { + for (i = 0; i < 64; i++) { usec_delay(50); mdic = E1000_READ_REG(hw, MDIC); - if(mdic & E1000_MDIC_READY) break; + if (mdic & E1000_MDIC_READY) break; } - if(!(mdic & E1000_MDIC_READY)) { + if (!(mdic & E1000_MDIC_READY)) { DEBUGOUT("MDI Read did not complete\n"); return -E1000_ERR_PHY; } - if(mdic & E1000_MDIC_ERROR) { + if (mdic & E1000_MDIC_ERROR) { DEBUGOUT("MDI Error\n"); return -E1000_ERR_PHY; } @@ -3354,12 +3503,13 @@ em_write_phy_reg(struct em_hw *hw, if (em_swfw_sync_acquire(hw, swfw)) return -E1000_ERR_SWFW_SYNC; - if((hw->phy_type == em_phy_igp || + if ((hw->phy_type == em_phy_igp || + hw->phy_type == em_phy_igp_3 || hw->phy_type == em_phy_igp_2) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { ret_val = em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, (uint16_t)reg_addr); - if(ret_val) { + if (ret_val) { em_swfw_sync_release(hw, swfw); return ret_val; } @@ -3404,12 +3554,12 @@ em_write_phy_reg_ex(struct em_hw *hw, DEBUGFUNC("em_write_phy_reg_ex"); - if(reg_addr > MAX_PHY_REG_ADDRESS) { + if (reg_addr > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", reg_addr); return -E1000_ERR_PARAM; } - if(hw->mac_type > em_82543) { + if (hw->mac_type > em_82543) { /* Set up Op-code, Phy Address, register address, and data intended * for the PHY register in the MDI Control register. The MAC will take * care of interfacing with the PHY to send the desired data. @@ -3422,12 +3572,12 @@ em_write_phy_reg_ex(struct em_hw *hw, E1000_WRITE_REG(hw, MDIC, mdic); /* Poll the ready bit to see if the MDI read completed */ - for(i = 0; i < 641; i++) { + for (i = 0; i < 641; i++) { usec_delay(5); mdic = E1000_READ_REG(hw, MDIC); - if(mdic & E1000_MDIC_READY) break; + if (mdic & E1000_MDIC_READY) break; } - if(!(mdic & E1000_MDIC_READY)) { + if (!(mdic & E1000_MDIC_READY)) { DEBUGOUT("MDI Write did not complete\n"); return -E1000_ERR_PHY; } @@ -3539,7 +3689,7 @@ em_phy_hw_reset(struct em_hw *hw) DEBUGOUT("Resetting Phy...\n"); - if(hw->mac_type > em_82543) { + if (hw->mac_type > em_82543) { if ((hw->mac_type == em_80003es2lan) && (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { swfw = E1000_SWFW_PHY1_SM; @@ -3552,24 +3702,24 @@ em_phy_hw_reset(struct em_hw *hw) } /* Read the device control register and assert the E1000_CTRL_PHY_RST * bit. Then, take it out of reset. - * For pre-em_82571 hardware, we delay for 10ms between the assert + * For pre-em_82571 hardware, we delay for 10ms between the assert * and deassert. For em_82571 hardware and later, we instead delay * for 50us between and 10ms after the deassertion. */ ctrl = E1000_READ_REG(hw, CTRL); E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST); E1000_WRITE_FLUSH(hw); - - if (hw->mac_type < em_82571) + + if (hw->mac_type < em_82571) msec_delay(10); else usec_delay(100); - + E1000_WRITE_REG(hw, CTRL, ctrl); E1000_WRITE_FLUSH(hw); - + if (hw->mac_type >= em_82571) - msec_delay(10); + msec_delay_irq(10); em_swfw_sync_release(hw, swfw); } else { /* Read the Extended Device Control Register, assert the PHY_RESET_DIR @@ -3587,7 +3737,7 @@ em_phy_hw_reset(struct em_hw *hw) } usec_delay(150); - if((hw->mac_type == em_82541) || (hw->mac_type == em_82547)) { + if ((hw->mac_type == em_82541) || (hw->mac_type == em_82547)) { /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; @@ -3599,6 +3749,12 @@ em_phy_hw_reset(struct em_hw *hw) ret_val = em_get_phy_cfg_done(hw); em_release_software_semaphore(hw); + if ((hw->mac_type == em_ich8lan) && + (hw->phy_type == em_phy_igp_3)) { + ret_val = em_init_lcd_from_nvm(hw); + if (ret_val) + return ret_val; + } return ret_val; } @@ -3627,31 +3783,142 @@ em_phy_reset(struct em_hw *hw) case em_82541_rev_2: case em_82571: case em_82572: + case em_ich8lan: ret_val = em_phy_hw_reset(hw); - if(ret_val) + if (ret_val) return ret_val; + break; default: ret_val = em_read_phy_reg(hw, PHY_CTRL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data |= MII_CR_RESET; ret_val = em_write_phy_reg(hw, PHY_CTRL, phy_data); - if(ret_val) + if (ret_val) return ret_val; usec_delay(1); break; } - if(hw->phy_type == em_phy_igp || hw->phy_type == em_phy_igp_2) + if (hw->phy_type == em_phy_igp || hw->phy_type == em_phy_igp_2) em_phy_init_script(hw); return E1000_SUCCESS; } /****************************************************************************** +* Work-around for 82566 power-down: on D3 entry- +* 1) disable gigabit link +* 2) write VR power-down enable +* 3) read it back +* if successful continue, else issue LCD reset and repeat +* +* hw - struct containing variables accessed by shared code +******************************************************************************/ +void +em_phy_powerdown_workaround(struct em_hw *hw) +{ + int32_t reg; + uint16_t phy_data; + int32_t retry = 0; + + DEBUGFUNC("em_phy_powerdown_workaround"); + + if (hw->phy_type != em_phy_igp_3) + return; + + do { + /* Disable link */ + reg = E1000_READ_REG(hw, PHY_CTRL); + E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE | + E1000_PHY_CTRL_NOND0A_GBE_DISABLE); + + /* Write VR power-down enable */ + em_read_phy_reg(hw, IGP3_VR_CTRL, &phy_data); + em_write_phy_reg(hw, IGP3_VR_CTRL, phy_data | + IGP3_VR_CTRL_MODE_SHUT); + + /* Read it back and test */ + em_read_phy_reg(hw, IGP3_VR_CTRL, &phy_data); + if ((phy_data & IGP3_VR_CTRL_MODE_SHUT) || retry) + break; + + /* Issue PHY reset and repeat at most one more time */ + reg = E1000_READ_REG(hw, CTRL); + E1000_WRITE_REG(hw, CTRL, reg | E1000_CTRL_PHY_RST); + retry++; + } while (retry); + + return; + +} + +/****************************************************************************** +* Work-around for 82566 Kumeran PCS lock loss: +* On link status change (i.e. PCI reset, speed change) and link is up and +* speed is gigabit- +* 0) if workaround is optionally disabled do nothing +* 1) wait 1ms for Kumeran link to come up +* 2) check Kumeran Diagnostic register PCS lock loss bit +* 3) if not set the link is locked (all is good), otherwise... +* 4) reset the PHY +* 5) repeat up to 10 times +* Note: this is only called for IGP3 copper when speed is 1gb. +* +* hw - struct containing variables accessed by shared code +******************************************************************************/ +int32_t +em_kumeran_lock_loss_workaround(struct em_hw *hw) +{ + int32_t ret_val; + int32_t reg; + int32_t cnt; + uint16_t phy_data; + + if (hw->kmrn_lock_loss_workaround_disabled) + return E1000_SUCCESS; + + /* Make sure link is up before proceeding. If not just return. + * Attempting this while link is negotiating fouls up link + * stability */ + ret_val = em_read_phy_reg(hw, PHY_STATUS, &phy_data); + ret_val = em_read_phy_reg(hw, PHY_STATUS, &phy_data); + + if (phy_data & MII_SR_LINK_STATUS) { + for (cnt = 0; cnt < 10; cnt++) { + /* read once to clear */ + ret_val = em_read_phy_reg(hw, IGP3_KMRN_DIAG, &phy_data); + if (ret_val) + return ret_val; + /* and again to get new status */ + ret_val = em_read_phy_reg(hw, IGP3_KMRN_DIAG, &phy_data); + if (ret_val) + return ret_val; + + /* check for PCS lock */ + if (!(phy_data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS)) + return E1000_SUCCESS; + + /* Issue PHY reset */ + em_phy_hw_reset(hw); + msec_delay_irq(5); + } + /* Disable GigE link negotiation */ + reg = E1000_READ_REG(hw, PHY_CTRL); + E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE | + E1000_PHY_CTRL_NOND0A_GBE_DISABLE); + + /* unable to acquire PCS lock */ + return E1000_ERR_PHY; + } + + return E1000_SUCCESS; +} + +/****************************************************************************** * Probes the expected PHY address for known PHY IDs * * hw - Struct containing variables accessed by shared code @@ -3668,8 +3935,8 @@ em_detect_gig_phy(struct em_hw *hw) /* The 82571 firmware may still be configuring the PHY. In this * case, we cannot access the PHY until the configuration is done. So * we explicitly set the PHY values. */ - if(hw->mac_type == em_82571 || - hw->mac_type == em_82572) { + if (hw->mac_type == em_82571 || + hw->mac_type == em_82572) { hw->phy_id = IGP01E1000_I_PHY_ID; hw->phy_type = em_phy_igp_2; return E1000_SUCCESS; @@ -3686,44 +3953,50 @@ em_detect_gig_phy(struct em_hw *hw) /* Read the PHY ID Registers to identify which PHY is onboard. */ ret_val = em_read_phy_reg(hw, PHY_ID1, &phy_id_high); - if(ret_val) + if (ret_val) return ret_val; hw->phy_id = (uint32_t) (phy_id_high << 16); usec_delay(20); ret_val = em_read_phy_reg(hw, PHY_ID2, &phy_id_low); - if(ret_val) + if (ret_val) return ret_val; hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK); hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK; - switch(hw->mac_type) { + switch (hw->mac_type) { case em_82543: - if(hw->phy_id == M88E1000_E_PHY_ID) match = TRUE; + if (hw->phy_id == M88E1000_E_PHY_ID) match = TRUE; break; case em_82544: - if(hw->phy_id == M88E1000_I_PHY_ID) match = TRUE; + if (hw->phy_id == M88E1000_I_PHY_ID) match = TRUE; break; case em_82540: case em_82545: case em_82545_rev_3: case em_82546: case em_82546_rev_3: - if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE; + if (hw->phy_id == M88E1011_I_PHY_ID) match = TRUE; break; case em_82541: case em_82541_rev_2: case em_82547: case em_82547_rev_2: - if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE; + if (hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE; break; case em_82573: - if(hw->phy_id == M88E1111_I_PHY_ID) match = TRUE; + if (hw->phy_id == M88E1111_I_PHY_ID) match = TRUE; break; case em_80003es2lan: if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE; break; + case em_ich8lan: + if (hw->phy_id == IGP03E1000_E_PHY_ID) match = TRUE; + if (hw->phy_id == IFE_E_PHY_ID) match = TRUE; + if (hw->phy_id == IFE_PLUS_E_PHY_ID) match = TRUE; + if (hw->phy_id == IFE_C_E_PHY_ID) match = TRUE; + break; default: DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type); return -E1000_ERR_CONFIG; @@ -3752,14 +4025,14 @@ em_phy_reset_dsp(struct em_hw *hw) do { if (hw->phy_type != em_phy_gg82563) { ret_val = em_write_phy_reg(hw, 29, 0x001d); - if(ret_val) break; + if (ret_val) break; } ret_val = em_write_phy_reg(hw, 30, 0x00c1); - if(ret_val) break; + if (ret_val) break; ret_val = em_write_phy_reg(hw, 30, 0x0000); - if(ret_val) break; + if (ret_val) break; ret_val = E1000_SUCCESS; - } while(0); + } while (0); return ret_val; } @@ -3791,23 +4064,23 @@ em_phy_igp_get_info(struct em_hw *hw, /* Check polarity status */ ret_val = em_check_polarity(hw, &polarity); - if(ret_val) + if (ret_val) return ret_val; phy_info->cable_polarity = polarity; ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_info->mdix_mode = (phy_data & IGP01E1000_PSSR_MDIX) >> IGP01E1000_PSSR_MDIX_SHIFT; - if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == + if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { /* Local/Remote Receiver Information are only valid at 1000 Mbps */ ret_val = em_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> @@ -3817,19 +4090,19 @@ em_phy_igp_get_info(struct em_hw *hw, /* Get cable length */ ret_val = em_get_cable_length(hw, &min_length, &max_length); - if(ret_val) + if (ret_val) return ret_val; /* Translate to old method */ average = (max_length + min_length) / 2; - if(average <= em_igp_cable_length_50) + if (average <= em_igp_cable_length_50) phy_info->cable_length = em_cable_length_50; - else if(average <= em_igp_cable_length_80) + else if (average <= em_igp_cable_length_80) phy_info->cable_length = em_cable_length_50_80; - else if(average <= em_igp_cable_length_110) + else if (average <= em_igp_cable_length_110) phy_info->cable_length = em_cable_length_80_110; - else if(average <= em_igp_cable_length_140) + else if (average <= em_igp_cable_length_140) phy_info->cable_length = em_cable_length_110_140; else phy_info->cable_length = em_cable_length_140; @@ -3839,6 +4112,53 @@ em_phy_igp_get_info(struct em_hw *hw, } /****************************************************************************** +* Get PHY information from various PHY registers for ife PHY only. +* +* hw - Struct containing variables accessed by shared code +* phy_info - PHY information structure +******************************************************************************/ +int32_t +em_phy_ife_get_info(struct em_hw *hw, + struct em_phy_info *phy_info) +{ + int32_t ret_val; + uint16_t phy_data, polarity; + + DEBUGFUNC("em_phy_ife_get_info"); + + phy_info->downshift = (em_downshift)hw->speed_downgraded; + phy_info->extended_10bt_distance = em_10bt_ext_dist_enable_normal; + + ret_val = em_read_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, &phy_data); + if (ret_val) + return ret_val; + phy_info->polarity_correction = + (phy_data & IFE_PSC_AUTO_POLARITY_DISABLE) >> + IFE_PSC_AUTO_POLARITY_DISABLE_SHIFT; + + if (phy_info->polarity_correction == em_polarity_reversal_enabled) { + ret_val = em_check_polarity(hw, &polarity); + if (ret_val) + return ret_val; + } else { + /* Polarity is forced. */ + polarity = (phy_data & IFE_PSC_FORCE_POLARITY) >> + IFE_PSC_FORCE_POLARITY_SHIFT; + } + phy_info->cable_polarity = polarity; + + ret_val = em_read_phy_reg(hw, IFE_PHY_MDIX_CONTROL, &phy_data); + if (ret_val) + return ret_val; + + phy_info->mdix_mode = + (phy_data & (IFE_PMC_AUTO_MDIX | IFE_PMC_FORCE_MDIX)) >> + IFE_PMC_MDIX_MODE_SHIFT; + + return E1000_SUCCESS; +} + +/****************************************************************************** * Get PHY information from various PHY registers fot m88 PHY only. * * hw - Struct containing variables accessed by shared code @@ -3858,7 +4178,7 @@ em_phy_m88_get_info(struct em_hw *hw, phy_info->downshift = (em_downshift)hw->speed_downgraded; ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_info->extended_10bt_distance = @@ -3870,12 +4190,12 @@ em_phy_m88_get_info(struct em_hw *hw, /* Check polarity status */ ret_val = em_check_polarity(hw, &polarity); - if(ret_val) - return ret_val; + if (ret_val) + return ret_val; phy_info->cable_polarity = polarity; ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >> @@ -3898,7 +4218,7 @@ em_phy_m88_get_info(struct em_hw *hw, } ret_val = em_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> @@ -3935,27 +4255,30 @@ em_phy_get_info(struct em_hw *hw, phy_info->local_rx = em_1000t_rx_status_undefined; phy_info->remote_rx = em_1000t_rx_status_undefined; - if(hw->media_type != em_media_type_copper) { + if (hw->media_type != em_media_type_copper) { DEBUGOUT("PHY info is only valid for copper media\n"); return -E1000_ERR_CONFIG; } ret_val = em_read_phy_reg(hw, PHY_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_read_phy_reg(hw, PHY_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; - if((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) { + if ((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) { DEBUGOUT("PHY info is only valid if link is up\n"); return -E1000_ERR_CONFIG; } - if(hw->phy_type == em_phy_igp || + if (hw->phy_type == em_phy_igp || + hw->phy_type == em_phy_igp_3 || hw->phy_type == em_phy_igp_2) return em_phy_igp_get_info(hw, phy_info); + else if (hw->phy_type == em_phy_ife) + return em_phy_ife_get_info(hw, phy_info); else return em_phy_m88_get_info(hw, phy_info); } @@ -3965,7 +4288,7 @@ em_validate_mdi_setting(struct em_hw *hw) { DEBUGFUNC("em_validate_mdi_settings"); - if(!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) { + if (!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) { DEBUGOUT("Invalid MDI setting detected\n"); hw->mdix = 1; return -E1000_ERR_CONFIG; @@ -4012,7 +4335,7 @@ em_init_eeprom_params(struct em_hw *hw) eeprom->type = em_eeprom_microwire; eeprom->opcode_bits = 3; eeprom->delay_usec = 50; - if(eecd & E1000_EECD_SIZE) { + if (eecd & E1000_EECD_SIZE) { eeprom->word_size = 256; eeprom->address_bits = 8; } else { @@ -4080,7 +4403,7 @@ em_init_eeprom_params(struct em_hw *hw) } eeprom->use_eerd = TRUE; eeprom->use_eewr = TRUE; - if(em_is_onboard_nvm_eeprom(hw) == FALSE) { + if (em_is_onboard_nvm_eeprom(hw) == FALSE) { eeprom->type = em_eeprom_flash; eeprom->word_size = 2048; @@ -4104,6 +4427,35 @@ em_init_eeprom_params(struct em_hw *hw) eeprom->use_eerd = TRUE; eeprom->use_eewr = FALSE; break; + case em_ich8lan: + { + int32_t i = 0; + uint32_t flash_size = E1000_READ_ICH8_REG(hw, ICH8_FLASH_GFPREG); + + 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 = (flash_size & ICH8_GFPREG_BASE_MASK) * + ICH8_FLASH_SECTOR_SIZE; + + hw->flash_bank_size = ((flash_size >> 16) & ICH8_GFPREG_BASE_MASK) + 1; + hw->flash_bank_size -= (flash_size & ICH8_GFPREG_BASE_MASK); + hw->flash_bank_size *= ICH8_FLASH_SECTOR_SIZE; + hw->flash_bank_size /= 2 * sizeof(uint16_t); + + break; + } default: break; } @@ -4112,17 +4464,17 @@ em_init_eeprom_params(struct em_hw *hw) /* eeprom_size will be an enum [0..8] that maps to eeprom sizes 128B to * 32KB (incremented by powers of 2). */ - if(hw->mac_type <= em_82547_rev_2) { + if (hw->mac_type <= em_82547_rev_2) { /* Set to default value for initial eeprom read. */ eeprom->word_size = 64; ret_val = em_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size); - if(ret_val) + if (ret_val) return ret_val; eeprom_size = (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT; /* 256B eeprom size was not supported in earlier hardware, so we * bump eeprom_size up one to ensure that "1" (which maps to 256B) * is never the result used in the shifting logic below. */ - if(eeprom_size) + if (eeprom_size) eeprom_size++; } else { eeprom_size = (uint16_t)((eecd & E1000_EECD_SIZE_EX_MASK) >> @@ -4207,7 +4559,7 @@ em_shift_out_ee_bits(struct em_hw *hw, */ eecd &= ~E1000_EECD_DI; - if(data & mask) + if (data & mask) eecd |= E1000_EECD_DI; E1000_WRITE_REG(hw, EECD, eecd); @@ -4220,7 +4572,7 @@ em_shift_out_ee_bits(struct em_hw *hw, mask = mask >> 1; - } while(mask); + } while (mask); /* We leave the "DI" bit set to "0" when we leave this routine. */ eecd &= ~E1000_EECD_DI; @@ -4252,14 +4604,14 @@ em_shift_in_ee_bits(struct em_hw *hw, eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); data = 0; - for(i = 0; i < count; i++) { + for (i = 0; i < count; i++) { data = data << 1; em_raise_ee_clk(hw, &eecd); eecd = E1000_READ_REG(hw, EECD); eecd &= ~(E1000_EECD_DI); - if(eecd & E1000_EECD_DO) + if (eecd & E1000_EECD_DO) data |= 1; em_lower_ee_clk(hw, &eecd); @@ -4290,17 +4642,17 @@ em_acquire_eeprom(struct em_hw *hw) if (hw->mac_type != em_82573) { /* Request EEPROM Access */ - if(hw->mac_type > em_82544) { + if (hw->mac_type > em_82544) { eecd |= E1000_EECD_REQ; E1000_WRITE_REG(hw, EECD, eecd); eecd = E1000_READ_REG(hw, EECD); - while((!(eecd & E1000_EECD_GNT)) && + while ((!(eecd & E1000_EECD_GNT)) && (i < E1000_EEPROM_GRANT_ATTEMPTS)) { i++; usec_delay(5); eecd = E1000_READ_REG(hw, EECD); } - if(!(eecd & E1000_EECD_GNT)) { + if (!(eecd & E1000_EECD_GNT)) { eecd &= ~E1000_EECD_REQ; E1000_WRITE_REG(hw, EECD, eecd); DEBUGOUT("Could not acquire EEPROM grant\n"); @@ -4343,7 +4695,7 @@ em_standby_eeprom(struct em_hw *hw) eecd = E1000_READ_REG(hw, EECD); - if(eeprom->type == em_eeprom_microwire) { + if (eeprom->type == em_eeprom_microwire) { eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); E1000_WRITE_REG(hw, EECD, eecd); E1000_WRITE_FLUSH(hw); @@ -4366,7 +4718,7 @@ em_standby_eeprom(struct em_hw *hw) E1000_WRITE_REG(hw, EECD, eecd); E1000_WRITE_FLUSH(hw); usec_delay(eeprom->delay_usec); - } else if(eeprom->type == em_eeprom_spi) { + } else if (eeprom->type == em_eeprom_spi) { /* Toggle CS to flush commands */ eecd |= E1000_EECD_CS; E1000_WRITE_REG(hw, EECD, eecd); @@ -4400,7 +4752,7 @@ em_release_eeprom(struct em_hw *hw) E1000_WRITE_REG(hw, EECD, eecd); usec_delay(hw->eeprom.delay_usec); - } else if(hw->eeprom.type == em_eeprom_microwire) { + } else if (hw->eeprom.type == em_eeprom_microwire) { /* cleanup eeprom */ /* CS on Microwire is active-high */ @@ -4422,7 +4774,7 @@ em_release_eeprom(struct em_hw *hw) } /* Stop requesting EEPROM access */ - if(hw->mac_type > em_82544) { + if (hw->mac_type > em_82544) { eecd &= ~E1000_EECD_REQ; E1000_WRITE_REG(hw, EECD, eecd); } @@ -4460,12 +4812,12 @@ em_spi_eeprom_ready(struct em_hw *hw) retry_count += 5; em_standby_eeprom(hw); - } while(retry_count < EEPROM_MAX_RETRY_SPI); + } while (retry_count < EEPROM_MAX_RETRY_SPI); /* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and * only 0-5mSec on 5V devices) */ - if(retry_count >= EEPROM_MAX_RETRY_SPI) { + if (retry_count >= EEPROM_MAX_RETRY_SPI) { DEBUGOUT("SPI EEPROM Status error\n"); return -E1000_ERR_EEPROM; } @@ -4496,7 +4848,7 @@ em_read_eeprom(struct em_hw *hw, /* A check for invalid values: offset too large, too many words, and not * enough words. */ - if((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) || + if ((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) || (words == 0)) { DEBUGOUT("\"words\" parameter out of bounds\n"); return -E1000_ERR_EEPROM; @@ -4504,7 +4856,7 @@ em_read_eeprom(struct em_hw *hw, /* FLASH reads without acquiring the semaphore are safe */ if (em_is_onboard_nvm_eeprom(hw) == TRUE && - hw->eeprom.use_eerd == FALSE) { + hw->eeprom.use_eerd == FALSE) { switch (hw->mac_type) { case em_80003es2lan: break; @@ -4524,11 +4876,14 @@ em_read_eeprom(struct em_hw *hw, return ret_val; } - if(eeprom->type == em_eeprom_spi) { + if (eeprom->type == em_eeprom_ich8) + return em_read_eeprom_ich8(hw, offset, words, data); + + if (eeprom->type == em_eeprom_spi) { uint16_t word_in; uint8_t read_opcode = EEPROM_READ_OPCODE_SPI; - if(em_spi_eeprom_ready(hw)) { + if (em_spi_eeprom_ready(hw)) { em_release_eeprom(hw); return -E1000_ERR_EEPROM; } @@ -4536,7 +4891,7 @@ em_read_eeprom(struct em_hw *hw, em_standby_eeprom(hw); /* Some SPI eeproms use the 8th address bit embedded in the opcode */ - if((eeprom->address_bits == 8) && (offset >= 128)) + if ((eeprom->address_bits == 8) && (offset >= 128)) read_opcode |= EEPROM_A8_OPCODE_SPI; /* Send the READ command (opcode + addr) */ @@ -4552,7 +4907,7 @@ em_read_eeprom(struct em_hw *hw, word_in = em_shift_in_ee_bits(hw, 16); data[i] = (word_in >> 8) | (word_in << 8); } - } else if(eeprom->type == em_eeprom_microwire) { + } else if (eeprom->type == em_eeprom_microwire) { for (i = 0; i < words; i++) { /* Send the READ command (opcode + addr) */ em_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE, @@ -4596,14 +4951,14 @@ em_read_eeprom_eerd(struct em_hw *hw, E1000_WRITE_REG(hw, EERD, eerd); error = em_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ); - - if(error) { + + if (error) { break; } data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA); - + } - + return error; } @@ -4629,24 +4984,24 @@ em_write_eeprom_eewr(struct em_hw *hw, return -E1000_ERR_SWFW_SYNC; for (i = 0; i < words; i++) { - register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) | - ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) | + register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) | + ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) | E1000_EEPROM_RW_REG_START; error = em_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE); - if(error) { + if (error) { break; - } + } E1000_WRITE_REG(hw, EEWR, register_value); - + error = em_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE); - - if(error) { + + if (error) { break; - } + } } - + em_swfw_sync_release(hw, E1000_SWFW_EEP_SM); return error; } @@ -4663,13 +5018,13 @@ em_poll_eerd_eewr_done(struct em_hw *hw, int eerd) uint32_t i, reg = 0; int32_t done = E1000_ERR_EEPROM; - for(i = 0; i < attempts; i++) { - if(eerd == E1000_EEPROM_POLL_READ) + for (i = 0; i < attempts; i++) { + if (eerd == E1000_EEPROM_POLL_READ) reg = E1000_READ_REG(hw, EERD); - else + else reg = E1000_READ_REG(hw, EEWR); - if(reg & E1000_EEPROM_RW_REG_DONE) { + if (reg & E1000_EEPROM_RW_REG_DONE) { done = E1000_SUCCESS; break; } @@ -4691,14 +5046,17 @@ em_is_onboard_nvm_eeprom(struct em_hw *hw) DEBUGFUNC("em_is_onboard_nvm_eeprom"); - if(hw->mac_type == em_82573) { + if (hw->mac_type == em_ich8lan) + return FALSE; + + if (hw->mac_type == em_82573) { eecd = E1000_READ_REG(hw, EECD); /* Isolate bits 15 & 16 */ eecd = ((eecd >> 15) & 0x03); /* If both bits are set, device is Flash type */ - if(eecd == 0x03) { + if (eecd == 0x03) { return FALSE; } } @@ -4741,15 +5099,29 @@ em_validate_eeprom_checksum(struct em_hw *hw) } } - for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { - if(em_read_eeprom(hw, i, 1, &eeprom_data) < 0) { + if (hw->mac_type == em_ich8lan) { + /* Drivers must allocate the shadow ram structure for the + * EEPROM checksum to be updated. Otherwise, this bit as well + * as the checksum must both be set correctly for this + * validation to pass. + */ + em_read_eeprom(hw, 0x19, 1, &eeprom_data); + if ((eeprom_data & 0x40) == 0) { + eeprom_data |= 0x40; + em_write_eeprom(hw, 0x19, 1, &eeprom_data); + em_update_eeprom_checksum(hw); + } + } + + for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { + if (em_read_eeprom(hw, i, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } checksum += eeprom_data; } - if(checksum == (uint16_t) EEPROM_SUM) + if (checksum == (uint16_t) EEPROM_SUM) return E1000_SUCCESS; else { DEBUGOUT("EEPROM Checksum Invalid\n"); @@ -4768,24 +5140,33 @@ em_validate_eeprom_checksum(struct em_hw *hw) int32_t em_update_eeprom_checksum(struct em_hw *hw) { + uint32_t ctrl_ext; uint16_t checksum = 0; uint16_t i, eeprom_data; DEBUGFUNC("em_update_eeprom_checksum"); - for(i = 0; i < EEPROM_CHECKSUM_REG; i++) { - if(em_read_eeprom(hw, i, 1, &eeprom_data) < 0) { + for (i = 0; i < EEPROM_CHECKSUM_REG; i++) { + if (em_read_eeprom(hw, i, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } checksum += eeprom_data; } checksum = (uint16_t) EEPROM_SUM - checksum; - if(em_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) { + if (em_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) { DEBUGOUT("EEPROM Write Error\n"); return -E1000_ERR_EEPROM; } else if (hw->eeprom.type == em_eeprom_flash) { em_commit_shadow_ram(hw); + } else if (hw->eeprom.type == em_eeprom_ich8) { + em_commit_shadow_ram(hw); + /* Reload the EEPROM, or else modifications will not appear + * until after next adapter reset. */ + ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_EE_RST; + E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + msec_delay(10); } return E1000_SUCCESS; } @@ -4815,21 +5196,24 @@ em_write_eeprom(struct em_hw *hw, /* A check for invalid values: offset too large, too many words, and not * enough words. */ - if((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) || + if ((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) || (words == 0)) { DEBUGOUT("\"words\" parameter out of bounds\n"); return -E1000_ERR_EEPROM; } /* 82573 writes only through eewr */ - if(eeprom->use_eewr == TRUE) + if (eeprom->use_eewr == TRUE) return em_write_eeprom_eewr(hw, offset, words, data); + if (eeprom->type == em_eeprom_ich8) + return em_write_eeprom_ich8(hw, offset, words, data); + /* Prepare the EEPROM for writing */ if (em_acquire_eeprom(hw) != E1000_SUCCESS) return -E1000_ERR_EEPROM; - if(eeprom->type == em_eeprom_microwire) { + if (eeprom->type == em_eeprom_microwire) { status = em_write_eeprom_microwire(hw, offset, words, data); } else { status = em_write_eeprom_spi(hw, offset, words, data); @@ -4865,7 +5249,7 @@ em_write_eeprom_spi(struct em_hw *hw, while (widx < words) { uint8_t write_opcode = EEPROM_WRITE_OPCODE_SPI; - if(em_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM; + if (em_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM; em_standby_eeprom(hw); @@ -4876,7 +5260,7 @@ em_write_eeprom_spi(struct em_hw *hw, em_standby_eeprom(hw); /* Some SPI eeproms use the 8th address bit embedded in the opcode */ - if((eeprom->address_bits == 8) && (offset >= 128)) + if ((eeprom->address_bits == 8) && (offset >= 128)) write_opcode |= EEPROM_A8_OPCODE_SPI; /* Send the Write command (8-bit opcode + addr) */ @@ -4898,7 +5282,7 @@ em_write_eeprom_spi(struct em_hw *hw, * operation, while the smaller eeproms are capable of an 8-byte * PAGE WRITE operation. Break the inner loop to pass new address */ - if((((offset + widx)*2) % eeprom->page_size) == 0) { + if ((((offset + widx)*2) % eeprom->page_size) == 0) { em_standby_eeprom(hw); break; } @@ -4964,12 +5348,12 @@ em_write_eeprom_microwire(struct em_hw *hw, * signal that the command has been completed by raising the DO signal. * If DO does not go high in 10 milliseconds, then error out. */ - for(i = 0; i < 200; i++) { + for (i = 0; i < 200; i++) { eecd = E1000_READ_REG(hw, EECD); - if(eecd & E1000_EECD_DO) break; + if (eecd & E1000_EECD_DO) break; usec_delay(50); } - if(i == 200) { + if (i == 200) { DEBUGOUT("EEPROM Write did not complete\n"); return -E1000_ERR_EEPROM; } @@ -5012,11 +5396,17 @@ em_commit_shadow_ram(struct em_hw *hw) uint32_t flop = 0; uint32_t i = 0; int32_t error = E1000_SUCCESS; - - /* The flop register will be used to determine if flash type is STM */ - flop = E1000_READ_REG(hw, FLOP); + uint32_t old_bank_offset = 0; + uint32_t new_bank_offset = 0; + uint32_t sector_retries = 0; + uint8_t low_byte = 0; + uint8_t high_byte = 0; + uint8_t temp_byte = 0; + boolean_t sector_write_failed = FALSE; if (hw->mac_type == em_82573) { + /* The flop register will be used to determine if flash type is STM */ + flop = E1000_READ_REG(hw, FLOP); for (i=0; i < attempts; i++) { eecd = E1000_READ_REG(hw, EECD); if ((eecd & E1000_EECD_FLUPD) == 0) { @@ -5050,6 +5440,106 @@ em_commit_shadow_ram(struct em_hw *hw) } } + if (hw->mac_type == em_ich8lan && hw->eeprom_shadow_ram != NULL) { + /* We're writing to the opposite bank so if we're on bank 1, + * write to bank 0 etc. We also need to erase the segment that + * is going to be written */ + if (!(E1000_READ_REG(hw, EECD) & E1000_EECD_SEC1VAL)) { + new_bank_offset = hw->flash_bank_size * 2; + old_bank_offset = 0; + em_erase_ich8_4k_segment(hw, 1); + } else { + old_bank_offset = hw->flash_bank_size * 2; + new_bank_offset = 0; + em_erase_ich8_4k_segment(hw, 0); + } + + do { + sector_write_failed = FALSE; + /* Loop for every byte in the shadow RAM, + * which is in units of words. */ + for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { + /* Determine whether to write the value stored + * in the other NVM bank or a modified value stored + * in the shadow RAM */ + if (hw->eeprom_shadow_ram[i].modified == TRUE) { + low_byte = (uint8_t)hw->eeprom_shadow_ram[i].eeprom_word; + em_read_ich8_byte(hw, (i << 1) + old_bank_offset, + &temp_byte); + usec_delay(100); + error = em_verify_write_ich8_byte(hw, + (i << 1) + new_bank_offset, + low_byte); + if (error != E1000_SUCCESS) + sector_write_failed = TRUE; + high_byte = + (uint8_t)(hw->eeprom_shadow_ram[i].eeprom_word >> 8); + em_read_ich8_byte(hw, (i << 1) + old_bank_offset + 1, + &temp_byte); + usec_delay(100); + } else { + em_read_ich8_byte(hw, (i << 1) + old_bank_offset, + &low_byte); + usec_delay(100); + error = em_verify_write_ich8_byte(hw, + (i << 1) + new_bank_offset, low_byte); + if (error != E1000_SUCCESS) + sector_write_failed = TRUE; + em_read_ich8_byte(hw, (i << 1) + old_bank_offset + 1, + &high_byte); + } + + /* If the word is 0x13, then make sure the signature bits + * (15:14) are 11b until the commit has completed. + * This will allow us to write 10b which indicates the + * signature is valid. We want to do this after the write + * has completed so that we don't mark the segment valid + * while the write is still in progress */ + if (i == E1000_ICH8_NVM_SIG_WORD) + high_byte = E1000_ICH8_NVM_SIG_MASK | high_byte; + + error = em_verify_write_ich8_byte(hw, + (i << 1) + new_bank_offset + 1, high_byte); + if (error != E1000_SUCCESS) + sector_write_failed = TRUE; + + if (sector_write_failed == FALSE) { + /* Clear the now not used entry in the cache */ + hw->eeprom_shadow_ram[i].modified = FALSE; + hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF; + } + } + + /* Don't bother writing the segment valid bits if sector + * programming failed. */ + if (sector_write_failed == FALSE) { + /* Finally validate the new segment by setting bit 15:14 + * to 10b in word 0x13 , this can be done without an + * erase as well since these bits are 11 to start with + * and we need to change bit 14 to 0b */ + em_read_ich8_byte(hw, + E1000_ICH8_NVM_SIG_WORD * 2 + 1 + new_bank_offset, + &high_byte); + high_byte &= 0xBF; + error = em_verify_write_ich8_byte(hw, + E1000_ICH8_NVM_SIG_WORD * 2 + 1 + new_bank_offset, + high_byte); + if (error != E1000_SUCCESS) + sector_write_failed = TRUE; + + /* And invalidate the previously valid segment by setting + * its signature word (0x13) high_byte to 0b. This can be + * done without an erase because flash erase sets all bits + * to 1's. We can write 1's to 0's without an erase */ + error = em_verify_write_ich8_byte(hw, + E1000_ICH8_NVM_SIG_WORD * 2 + 1 + old_bank_offset, + 0); + if (error != E1000_SUCCESS) + sector_write_failed = TRUE; + } + } while (++sector_retries < 10 && sector_write_failed == TRUE); + } + return error; } @@ -5069,7 +5559,7 @@ em_read_part_num(struct em_hw *hw, DEBUGFUNC("em_read_part_num"); /* Get word 0 from EEPROM */ - if(em_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { + if (em_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } @@ -5077,7 +5567,7 @@ em_read_part_num(struct em_hw *hw, *part_num = (uint32_t) (eeprom_data << 16); /* Get word 1 from EEPROM */ - if(em_read_eeprom(hw, ++offset, 1, &eeprom_data) < 0) { + if (em_read_eeprom(hw, ++offset, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } @@ -5101,9 +5591,9 @@ em_read_mac_addr(struct em_hw * hw) DEBUGFUNC("em_read_mac_addr"); - for(i = 0; i < NODE_ADDRESS_SIZE; i += 2) { + for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) { offset = i >> 1; - if(em_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { + if (em_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } @@ -5118,12 +5608,12 @@ em_read_mac_addr(struct em_hw * hw) case em_82546_rev_3: case em_82571: case em_80003es2lan: - if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) + if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) hw->perm_mac_addr[5] ^= 0x01; break; } - for(i = 0; i < NODE_ADDRESS_SIZE; i++) + for (i = 0; i < NODE_ADDRESS_SIZE; i++) hw->mac_addr[i] = hw->perm_mac_addr[i]; return E1000_SUCCESS; } @@ -5157,11 +5647,16 @@ em_init_rx_addrs(struct em_hw *hw) * the other port. */ if ((hw->mac_type == em_82571) && (hw->laa_is_present == TRUE)) rar_num -= 1; + if (hw->mac_type == em_ich8lan) + rar_num = E1000_RAR_ENTRIES_ICH8LAN; + /* Zero out the other 15 receive addresses. */ DEBUGOUT("Clearing RAR[1-15]\n"); - for(i = 1; i < rar_num; i++) { + for (i = 1; i < rar_num; i++) { E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); + E1000_WRITE_FLUSH(hw); E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); + E1000_WRITE_FLUSH(hw); } } @@ -5190,7 +5685,7 @@ em_mc_addr_list_update(struct em_hw *hw, uint32_t i; uint32_t num_rar_entry; uint32_t num_mta_entry; - + DEBUGFUNC("em_mc_addr_list_update"); /* Set the new number of MC addresses that we are being requested to use. */ @@ -5199,26 +5694,33 @@ em_mc_addr_list_update(struct em_hw *hw, /* Clear RAR[1-15] */ DEBUGOUT(" Clearing RAR[1-15]\n"); num_rar_entry = E1000_RAR_ENTRIES; + if (hw->mac_type == em_ich8lan) + num_rar_entry = E1000_RAR_ENTRIES_ICH8LAN; /* Reserve a spot for the Locally Administered Address to work around * an 82571 issue in which a reset on one port will reload the MAC on * the other port. */ if ((hw->mac_type == em_82571) && (hw->laa_is_present == TRUE)) num_rar_entry -= 1; - for(i = rar_used_count; i < num_rar_entry; i++) { + for (i = rar_used_count; i < num_rar_entry; i++) { E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); + E1000_WRITE_FLUSH(hw); E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); + E1000_WRITE_FLUSH(hw); } /* Clear the MTA */ DEBUGOUT(" Clearing MTA\n"); num_mta_entry = E1000_NUM_MTA_REGISTERS; - for(i = 0; i < num_mta_entry; i++) { + if (hw->mac_type == em_ich8lan) + num_mta_entry = E1000_NUM_MTA_REGISTERS_ICH8LAN; + for (i = 0; i < num_mta_entry; i++) { E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); + E1000_WRITE_FLUSH(hw); } /* Add the new addresses */ - for(i = 0; i < mc_addr_count; i++) { + for (i = 0; i < mc_addr_count; i++) { DEBUGOUT(" Adding the multicast addresses:\n"); DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i, mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad)], @@ -5270,24 +5772,46 @@ em_hash_mc_addr(struct em_hw *hw, * LSB MSB */ case 0: - /* [47:36] i.e. 0x563 for above example address */ - hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4)); + if (hw->mac_type == em_ich8lan) { + /* [47:38] i.e. 0x158 for above example address */ + hash_value = ((mc_addr[4] >> 6) | (((uint16_t) mc_addr[5]) << 2)); + } else { + /* [47:36] i.e. 0x563 for above example address */ + hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4)); + } break; case 1: - /* [46:35] i.e. 0xAC6 for above example address */ - hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5)); + if (hw->mac_type == em_ich8lan) { + /* [46:37] i.e. 0x2B1 for above example address */ + hash_value = ((mc_addr[4] >> 5) | (((uint16_t) mc_addr[5]) << 3)); + } else { + /* [46:35] i.e. 0xAC6 for above example address */ + hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5)); + } break; case 2: - /* [45:34] i.e. 0x5D8 for above example address */ - hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6)); + if (hw->mac_type == em_ich8lan) { + /*[45:36] i.e. 0x163 for above example address */ + hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4)); + } else { + /* [45:34] i.e. 0x5D8 for above example address */ + hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6)); + } break; case 3: - /* [43:32] i.e. 0x634 for above example address */ - hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8)); + if (hw->mac_type == em_ich8lan) { + /* [43:34] i.e. 0x18D for above example address */ + hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6)); + } else { + /* [43:32] i.e. 0x634 for above example address */ + hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8)); + } break; } hash_value &= 0xFFF; + if (hw->mac_type == em_ich8lan) + hash_value &= 0x3FF; return hash_value; } @@ -5315,6 +5839,8 @@ em_mta_set(struct em_hw *hw, * register are determined by the lower 5 bits of the value. */ hash_reg = (hash_value >> 5) & 0x7F; + if (hw->mac_type == em_ich8lan) + hash_reg &= 0x1F; hash_bit = hash_value & 0x1F; mta = E1000_READ_REG_ARRAY(hw, MTA, hash_reg); @@ -5325,12 +5851,15 @@ em_mta_set(struct em_hw *hw, * in the MTA, save off the previous entry before writing and * restore the old value after writing. */ - if((hw->mac_type == em_82544) && ((hash_reg & 0x1) == 1)) { + if ((hw->mac_type == em_82544) && ((hash_reg & 0x1) == 1)) { temp = E1000_READ_REG_ARRAY(hw, MTA, (hash_reg - 1)); E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta); + E1000_WRITE_FLUSH(hw); E1000_WRITE_REG_ARRAY(hw, MTA, (hash_reg - 1), temp); + E1000_WRITE_FLUSH(hw); } else { E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta); + E1000_WRITE_FLUSH(hw); } } @@ -5387,7 +5916,9 @@ em_rar_set(struct em_hw *hw, } E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low); + E1000_WRITE_FLUSH(hw); E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high); + E1000_WRITE_FLUSH(hw); } /****************************************************************************** @@ -5404,12 +5935,18 @@ em_write_vfta(struct em_hw *hw, { uint32_t temp; - if((hw->mac_type == em_82544) && ((offset & 0x1) == 1)) { + if (hw->mac_type == em_ich8lan) + return; + + if ((hw->mac_type == em_82544) && ((offset & 0x1) == 1)) { temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1)); E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value); + E1000_WRITE_FLUSH(hw); E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp); + E1000_WRITE_FLUSH(hw); } else { E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value); + E1000_WRITE_FLUSH(hw); } } @@ -5426,6 +5963,9 @@ em_clear_vfta(struct em_hw *hw) uint32_t vfta_offset = 0; uint32_t vfta_bit_in_reg = 0; + if (hw->mac_type == em_ich8lan) + return; + if (hw->mac_type == em_82573) { if (hw->mng_cookie.vlan_id != 0) { /* The VFTA is a 4096b bit-field, each identifying a single VLAN @@ -5445,6 +5985,7 @@ em_clear_vfta(struct em_hw *hw) * manageability unit */ vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0; E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value); + E1000_WRITE_FLUSH(hw); } } @@ -5460,7 +6001,7 @@ em_id_led_init(struct em_hw * hw) DEBUGFUNC("em_id_led_init"); - if(hw->mac_type < em_82540) { + if (hw->mac_type < em_82540) { /* Nothing to do */ return E1000_SUCCESS; } @@ -5470,15 +6011,24 @@ em_id_led_init(struct em_hw * hw) hw->ledctl_mode1 = hw->ledctl_default; hw->ledctl_mode2 = hw->ledctl_default; - if(em_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) { + if (em_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } - if((eeprom_data== ID_LED_RESERVED_0000) || - (eeprom_data == ID_LED_RESERVED_FFFF)) eeprom_data = ID_LED_DEFAULT; - for(i = 0; i < 4; i++) { + + if ((hw->mac_type == em_82573) && + (eeprom_data == ID_LED_RESERVED_82573)) + eeprom_data = ID_LED_DEFAULT_82573; + else if ((eeprom_data == ID_LED_RESERVED_0000) || + (eeprom_data == ID_LED_RESERVED_FFFF)) { + if (hw->mac_type == em_ich8lan) + eeprom_data = ID_LED_DEFAULT_ICH8LAN; + else + eeprom_data = ID_LED_DEFAULT; + } + for (i = 0; i < 4; i++) { temp = (eeprom_data >> (i << 2)) & led_mask; - switch(temp) { + switch (temp) { case ID_LED_ON1_DEF2: case ID_LED_ON1_ON2: case ID_LED_ON1_OFF2: @@ -5495,7 +6045,7 @@ em_id_led_init(struct em_hw * hw) /* Do nothing */ break; } - switch(temp) { + switch (temp) { case ID_LED_DEF1_ON2: case ID_LED_ON1_ON2: case ID_LED_OFF1_ON2: @@ -5529,7 +6079,7 @@ em_setup_led(struct em_hw *hw) DEBUGFUNC("em_setup_led"); - switch(hw->mac_type) { + switch (hw->mac_type) { case em_82542_rev2_0: case em_82542_rev2_1: case em_82543: @@ -5543,16 +6093,16 @@ em_setup_led(struct em_hw *hw) /* Turn off PHY Smart Power Down (if enabled) */ ret_val = em_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &hw->phy_spd_default); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_write_phy_reg(hw, IGP01E1000_GMII_FIFO, (uint16_t)(hw->phy_spd_default & ~IGP01E1000_GMII_SPD)); - if(ret_val) + if (ret_val) return ret_val; - /* Fall Through */ + /* FALLTHROUGH */ default: - if(hw->media_type == em_media_type_fiber) { + if (hw->media_type == em_media_type_fiber) { ledctl = E1000_READ_REG(hw, LEDCTL); /* Save current LEDCTL settings */ hw->ledctl_default = ledctl; @@ -5563,7 +6113,7 @@ em_setup_led(struct em_hw *hw) ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT); E1000_WRITE_REG(hw, LEDCTL, ledctl); - } else if(hw->media_type == em_media_type_copper) + } else if (hw->media_type == em_media_type_copper) E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); break; } @@ -5571,6 +6121,45 @@ em_setup_led(struct em_hw *hw) return E1000_SUCCESS; } + +/****************************************************************************** + * Used on 82571 and later Si that has LED blink bits. + * Callers must use their own timer and should have already called + * em_id_led_init() + * Call em_cleanup led() to stop blinking + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +int32_t +em_blink_led_start(struct em_hw *hw) +{ + int16_t i; + uint32_t ledctl_blink = 0; + + DEBUGFUNC("em_id_led_blink_on"); + + if (hw->mac_type < em_82571) { + /* Nothing to do */ + return E1000_SUCCESS; + } + if (hw->media_type == em_media_type_fiber) { + /* always blink LED0 for PCI-E fiber */ + ledctl_blink = E1000_LEDCTL_LED0_BLINK | + (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); + } else { + /* set the blink bit for each LED that's "on" (0x0E) in ledctl_mode2 */ + ledctl_blink = hw->ledctl_mode2; + for (i=0; i < 4; i++) + if (((hw->ledctl_mode2 >> (i * 8)) & 0xFF) == + E1000_LEDCTL_MODE_LED_ON) + ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << (i * 8)); + } + + E1000_WRITE_REG(hw, LEDCTL, ledctl_blink); + + return E1000_SUCCESS; +} + /****************************************************************************** * Restores the saved state of the SW controlable LED. * @@ -5583,7 +6172,7 @@ em_cleanup_led(struct em_hw *hw) DEBUGFUNC("em_cleanup_led"); - switch(hw->mac_type) { + switch (hw->mac_type) { case em_82542_rev2_0: case em_82542_rev2_1: case em_82543: @@ -5597,10 +6186,14 @@ em_cleanup_led(struct em_hw *hw) /* Turn on PHY Smart Power Down (if previously enabled) */ ret_val = em_write_phy_reg(hw, IGP01E1000_GMII_FIFO, hw->phy_spd_default); - if(ret_val) + if (ret_val) return ret_val; - /* Fall Through */ + /* FALLTHROUGH */ default: + if (hw->phy_type == em_phy_ife) { + em_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0); + break; + } /* Restore LEDCTL settings */ E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default); break; @@ -5621,7 +6214,7 @@ em_led_on(struct em_hw *hw) DEBUGFUNC("em_led_on"); - switch(hw->mac_type) { + switch (hw->mac_type) { case em_82542_rev2_0: case em_82542_rev2_1: case em_82543: @@ -5630,7 +6223,7 @@ em_led_on(struct em_hw *hw) ctrl |= E1000_CTRL_SWDPIO0; break; case em_82544: - if(hw->media_type == em_media_type_fiber) { + if (hw->media_type == em_media_type_fiber) { /* Set SW Defineable Pin 0 to turn on the LED */ ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; @@ -5641,11 +6234,14 @@ em_led_on(struct em_hw *hw) } break; default: - if(hw->media_type == em_media_type_fiber) { + if (hw->media_type == em_media_type_fiber) { /* Clear SW Defineable Pin 0 to turn on the LED */ ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; - } else if(hw->media_type == em_media_type_copper) { + } else if (hw->phy_type == em_phy_ife) { + em_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, + (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON)); + } else if (hw->media_type == em_media_type_copper) { E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2); return E1000_SUCCESS; } @@ -5669,7 +6265,7 @@ em_led_off(struct em_hw *hw) DEBUGFUNC("em_led_off"); - switch(hw->mac_type) { + switch (hw->mac_type) { case em_82542_rev2_0: case em_82542_rev2_1: case em_82543: @@ -5678,7 +6274,7 @@ em_led_off(struct em_hw *hw) ctrl |= E1000_CTRL_SWDPIO0; break; case em_82544: - if(hw->media_type == em_media_type_fiber) { + if (hw->media_type == em_media_type_fiber) { /* Clear SW Defineable Pin 0 to turn off the LED */ ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; @@ -5689,11 +6285,14 @@ em_led_off(struct em_hw *hw) } break; default: - if(hw->media_type == em_media_type_fiber) { + if (hw->media_type == em_media_type_fiber) { /* Set SW Defineable Pin 0 to turn off the LED */ ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; - } else if(hw->media_type == em_media_type_copper) { + } else if (hw->phy_type == em_phy_ife) { + em_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, + (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF)); + } else if (hw->media_type == em_media_type_copper) { E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); return E1000_SUCCESS; } @@ -5731,12 +6330,16 @@ em_clear_hw_cntrs(struct em_hw *hw) temp = E1000_READ_REG(hw, XOFFRXC); temp = E1000_READ_REG(hw, XOFFTXC); temp = E1000_READ_REG(hw, FCRUC); + + if (hw->mac_type != em_ich8lan) { temp = E1000_READ_REG(hw, PRC64); temp = E1000_READ_REG(hw, PRC127); temp = E1000_READ_REG(hw, PRC255); temp = E1000_READ_REG(hw, PRC511); temp = E1000_READ_REG(hw, PRC1023); temp = E1000_READ_REG(hw, PRC1522); + } + temp = E1000_READ_REG(hw, GPRC); temp = E1000_READ_REG(hw, BPRC); temp = E1000_READ_REG(hw, MPRC); @@ -5756,16 +6359,20 @@ em_clear_hw_cntrs(struct em_hw *hw) temp = E1000_READ_REG(hw, TOTH); temp = E1000_READ_REG(hw, TPR); temp = E1000_READ_REG(hw, TPT); + + if (hw->mac_type != em_ich8lan) { temp = E1000_READ_REG(hw, PTC64); temp = E1000_READ_REG(hw, PTC127); temp = E1000_READ_REG(hw, PTC255); temp = E1000_READ_REG(hw, PTC511); temp = E1000_READ_REG(hw, PTC1023); temp = E1000_READ_REG(hw, PTC1522); + } + temp = E1000_READ_REG(hw, MPTC); temp = E1000_READ_REG(hw, BPTC); - if(hw->mac_type < em_82543) return; + if (hw->mac_type < em_82543) return; temp = E1000_READ_REG(hw, ALGNERRC); temp = E1000_READ_REG(hw, RXERRC); @@ -5774,16 +6381,19 @@ em_clear_hw_cntrs(struct em_hw *hw) temp = E1000_READ_REG(hw, TSCTC); temp = E1000_READ_REG(hw, TSCTFC); - if(hw->mac_type <= em_82544) return; + if (hw->mac_type <= em_82544) return; temp = E1000_READ_REG(hw, MGTPRC); temp = E1000_READ_REG(hw, MGTPDC); temp = E1000_READ_REG(hw, MGTPTC); - if(hw->mac_type <= em_82547_rev_2) return; + if (hw->mac_type <= em_82547_rev_2) return; temp = E1000_READ_REG(hw, IAC); temp = E1000_READ_REG(hw, ICRXOC); + + if (hw->mac_type == em_ich8lan) return; + temp = E1000_READ_REG(hw, ICRXPTC); temp = E1000_READ_REG(hw, ICRXATC); temp = E1000_READ_REG(hw, ICTXPTC); @@ -5808,8 +6418,8 @@ em_reset_adaptive(struct em_hw *hw) { DEBUGFUNC("em_reset_adaptive"); - if(hw->adaptive_ifs) { - if(!hw->ifs_params_forced) { + if (hw->adaptive_ifs) { + if (!hw->ifs_params_forced) { hw->current_ifs_val = 0; hw->ifs_min_val = IFS_MIN; hw->ifs_max_val = IFS_MAX; @@ -5836,12 +6446,12 @@ em_update_adaptive(struct em_hw *hw) { DEBUGFUNC("em_update_adaptive"); - if(hw->adaptive_ifs) { - if((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) { - if(hw->tx_packet_delta > MIN_NUM_XMITS) { + if (hw->adaptive_ifs) { + if ((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) { + if (hw->tx_packet_delta > MIN_NUM_XMITS) { hw->in_ifs_mode = TRUE; - if(hw->current_ifs_val < hw->ifs_max_val) { - if(hw->current_ifs_val == 0) + if (hw->current_ifs_val < hw->ifs_max_val) { + if (hw->current_ifs_val == 0) hw->current_ifs_val = hw->ifs_min_val; else hw->current_ifs_val += hw->ifs_step_size; @@ -5849,7 +6459,7 @@ em_update_adaptive(struct em_hw *hw) } } } else { - if(hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) { + if (hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) { hw->current_ifs_val = 0; hw->in_ifs_mode = FALSE; E1000_WRITE_REG(hw, AIT, 0); @@ -5896,46 +6506,46 @@ em_tbi_adjust_stats(struct em_hw *hw, * This could be simplified if all environments supported * 64-bit integers. */ - if(carry_bit && ((stats->gorcl & 0x80000000) == 0)) + if (carry_bit && ((stats->gorcl & 0x80000000) == 0)) stats->gorch++; /* Is this a broadcast or multicast? Check broadcast first, * since the test for a multicast frame will test positive on * a broadcast frame. */ - if((mac_addr[0] == (uint8_t) 0xff) && (mac_addr[1] == (uint8_t) 0xff)) + if ((mac_addr[0] == (uint8_t) 0xff) && (mac_addr[1] == (uint8_t) 0xff)) /* Broadcast packet */ stats->bprc++; - else if(*mac_addr & 0x01) + else if (*mac_addr & 0x01) /* Multicast packet */ stats->mprc++; - if(frame_len == hw->max_frame_size) { + if (frame_len == hw->max_frame_size) { /* In this case, the hardware has overcounted the number of * oversize frames. */ - if(stats->roc > 0) + if (stats->roc > 0) stats->roc--; } /* Adjust the bin counters when the extra byte put the frame in the * wrong bin. Remember that the frame_len was adjusted above. */ - if(frame_len == 64) { + if (frame_len == 64) { stats->prc64++; stats->prc127--; - } else if(frame_len == 127) { + } else if (frame_len == 127) { stats->prc127++; stats->prc255--; - } else if(frame_len == 255) { + } else if (frame_len == 255) { stats->prc255++; stats->prc511--; - } else if(frame_len == 511) { + } else if (frame_len == 511) { stats->prc511++; stats->prc1023--; - } else if(frame_len == 1023) { + } else if (frame_len == 1023) { stats->prc1023++; stats->prc1522--; - } else if(frame_len == 1522) { + } else if (frame_len == 1522) { stats->prc1522++; } } @@ -5964,6 +6574,7 @@ em_get_bus_info(struct em_hw *hw) hw->bus_width = em_bus_width_pciex_1; break; case em_82571: + case em_ich8lan: case em_80003es2lan: hw->bus_type = em_bus_type_pci_express; hw->bus_speed = em_bus_speed_2500; @@ -5974,10 +6585,10 @@ em_get_bus_info(struct em_hw *hw) hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? em_bus_type_pcix : em_bus_type_pci; - if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) { + if (hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) { hw->bus_speed = (hw->bus_type == em_bus_type_pci) ? em_bus_speed_66 : em_bus_speed_120; - } else if(hw->bus_type == em_bus_type_pci) { + } else if (hw->bus_type == em_bus_type_pci) { hw->bus_speed = (status & E1000_STATUS_PCI66) ? em_bus_speed_66 : em_bus_speed_33; } else { @@ -6062,8 +6673,6 @@ em_get_cable_length(struct em_hw *hw, { int32_t ret_val; uint16_t agc_value = 0; - uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1; - uint16_t max_agc = 0; uint16_t i, phy_data; uint16_t cable_length; @@ -6072,11 +6681,11 @@ em_get_cable_length(struct em_hw *hw, *min_length = *max_length = 0; /* Use old method for Phy older than IGP */ - if(hw->phy_type == em_phy_m88) { + if (hw->phy_type == em_phy_m88) { ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> M88E1000_PSSR_CABLE_LENGTH_SHIFT; @@ -6135,36 +6744,38 @@ em_get_cable_length(struct em_hw *hw, return -E1000_ERR_PHY; break; } - } else if(hw->phy_type == em_phy_igp) { /* For IGP PHY */ + } else if (hw->phy_type == em_phy_igp) { /* For IGP PHY */ + uint16_t cur_agc_value; + uint16_t min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE; uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {IGP01E1000_PHY_AGC_A, IGP01E1000_PHY_AGC_B, IGP01E1000_PHY_AGC_C, IGP01E1000_PHY_AGC_D}; /* Read the AGC registers for all channels */ - for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { + for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { ret_val = em_read_phy_reg(hw, agc_reg_array[i], &phy_data); - if(ret_val) + if (ret_val) return ret_val; - cur_agc = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT; + cur_agc_value = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT; - /* Array bound check. */ - if((cur_agc >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) || - (cur_agc == 0)) + /* Value bound check. */ + if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) || + (cur_agc_value == 0)) return -E1000_ERR_PHY; - agc_value += cur_agc; + agc_value += cur_agc_value; /* Update minimal AGC value. */ - if(min_agc > cur_agc) - min_agc = cur_agc; + if (min_agc_value > cur_agc_value) + min_agc_value = cur_agc_value; } /* Remove the minimal AGC result for length < 50m */ - if(agc_value < IGP01E1000_PHY_CHANNEL_NUM * em_igp_cable_length_50) { - agc_value -= min_agc; + if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * em_igp_cable_length_50) { + agc_value -= min_agc_value; /* Get the average length of the remaining 3 channels */ agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1); @@ -6180,7 +6791,10 @@ em_get_cable_length(struct em_hw *hw, IGP01E1000_AGC_RANGE) : 0; *max_length = em_igp_cable_length_table[agc_value] + IGP01E1000_AGC_RANGE; - } else if (hw->phy_type == em_phy_igp_2) { + } else if (hw->phy_type == em_phy_igp_2 || + hw->phy_type == em_phy_igp_3) { + uint16_t cur_agc_index, max_agc_index = 0; + uint16_t min_agc_index = IGP02E1000_AGC_LENGTH_TABLE_SIZE - 1; uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = {IGP02E1000_PHY_AGC_A, IGP02E1000_PHY_AGC_B, @@ -6192,22 +6806,30 @@ em_get_cable_length(struct em_hw *hw, if (ret_val) return ret_val; - /* Getting bits 15:9, which represent the combination of course and + /* Getting bits 15:9, which represent the combination of course and * fine gain values. The result is a number that can be put into * the lookup table to obtain the approximate cable length. */ - cur_agc = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & - IGP02E1000_AGC_LENGTH_MASK; + cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & + IGP02E1000_AGC_LENGTH_MASK; - /* Remove min & max AGC values from calculation. */ - if (em_igp_2_cable_length_table[min_agc] > em_igp_2_cable_length_table[cur_agc]) - min_agc = cur_agc; - if (em_igp_2_cable_length_table[max_agc] < em_igp_2_cable_length_table[cur_agc]) - max_agc = cur_agc; + /* Array index bound check. */ + if ((cur_agc_index >= IGP02E1000_AGC_LENGTH_TABLE_SIZE) || + (cur_agc_index == 0)) + return -E1000_ERR_PHY; - agc_value += em_igp_2_cable_length_table[cur_agc]; + /* Remove min & max AGC values from calculation. */ + if (em_igp_2_cable_length_table[min_agc_index] > + em_igp_2_cable_length_table[cur_agc_index]) + min_agc_index = cur_agc_index; + if (em_igp_2_cable_length_table[max_agc_index] < + em_igp_2_cable_length_table[cur_agc_index]) + max_agc_index = cur_agc_index; + + agc_value += em_igp_2_cable_length_table[cur_agc_index]; } - agc_value -= (em_igp_2_cable_length_table[min_agc] + em_igp_2_cable_length_table[max_agc]); + agc_value -= (em_igp_2_cable_length_table[min_agc_index] + + em_igp_2_cable_length_table[max_agc_index]); agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); /* Calculate cable length with the error range of +/- 10 meters. */ @@ -6249,27 +6871,28 @@ em_check_polarity(struct em_hw *hw, /* return the Polarity bit in the Status register. */ ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >> M88E1000_PSSR_REV_POLARITY_SHIFT; - } else if(hw->phy_type == em_phy_igp || + } else if (hw->phy_type == em_phy_igp || + hw->phy_type == em_phy_igp_3 || hw->phy_type == em_phy_igp_2) { /* Read the Status register to check the speed */ ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; /* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to * find the polarity status */ - if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == + if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { /* Read the GIG initialization PCS register (0x00B4) */ ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG, &phy_data); - if(ret_val) + if (ret_val) return ret_val; /* Check the polarity bits */ @@ -6279,6 +6902,13 @@ em_check_polarity(struct em_hw *hw, * 100 Mbps this bit is always 0) */ *polarity = phy_data & IGP01E1000_PSSR_POLARITY_REVERSED; } + } else if (hw->phy_type == em_phy_ife) { + ret_val = em_read_phy_reg(hw, IFE_PHY_EXTENDED_STATUS_CONTROL, + &phy_data); + if (ret_val) + return ret_val; + *polarity = (phy_data & IFE_PESC_POLARITY_REVERSED) >> + IFE_PESC_POLARITY_REVERSED_SHIFT; } return E1000_SUCCESS; } @@ -6291,7 +6921,7 @@ em_check_polarity(struct em_hw *hw, * 1 - Downshift ocured. * * returns: - E1000_ERR_XXX - * E1000_SUCCESS + * E1000_SUCCESS * * For phy's older then IGP, this function reads the Downshift bit in the Phy * Specific Status register. For IGP phy's, it reads the Downgrade bit in the @@ -6306,11 +6936,12 @@ em_check_downshift(struct em_hw *hw) DEBUGFUNC("em_check_downshift"); - if(hw->phy_type == em_phy_igp || + if (hw->phy_type == em_phy_igp || + hw->phy_type == em_phy_igp_3 || hw->phy_type == em_phy_igp_2) { ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, &phy_data); - if(ret_val) + if (ret_val) return ret_val; hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; @@ -6318,11 +6949,14 @@ em_check_downshift(struct em_hw *hw) (hw->phy_type == em_phy_gg82563)) { ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >> M88E1000_PSSR_DOWNSHIFT_SHIFT; + } else if (hw->phy_type == em_phy_ife) { + /* em_phy_ife supports 10/100 speed only */ + hw->speed_downgraded = FALSE; } return E1000_SUCCESS; @@ -6355,40 +6989,42 @@ em_config_dsp_after_link_change(struct em_hw *hw, DEBUGFUNC("em_config_dsp_after_link_change"); - if(hw->phy_type != em_phy_igp) + if (hw->phy_type != em_phy_igp) return E1000_SUCCESS; - if(link_up) { + if (link_up) { ret_val = em_get_speed_and_duplex(hw, &speed, &duplex); - if(ret_val) { + if (ret_val) { DEBUGOUT("Error getting link speed and duplex\n"); return ret_val; } - if(speed == SPEED_1000) { + if (speed == SPEED_1000) { - em_get_cable_length(hw, &min_length, &max_length); + ret_val = em_get_cable_length(hw, &min_length, &max_length); + if (ret_val) + return ret_val; - if((hw->dsp_config_state == em_dsp_config_enabled) && + if ((hw->dsp_config_state == em_dsp_config_enabled) && min_length >= em_igp_cable_length_50) { - for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { + for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { ret_val = em_read_phy_reg(hw, dsp_reg_array[i], &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; ret_val = em_write_phy_reg(hw, dsp_reg_array[i], phy_data); - if(ret_val) + if (ret_val) return ret_val; } hw->dsp_config_state = em_dsp_config_activated; } - if((hw->ffe_config_state == em_ffe_config_enabled) && + if ((hw->ffe_config_state == em_ffe_config_enabled) && (min_length < em_igp_cable_length_50)) { uint16_t ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20; @@ -6397,70 +7033,70 @@ em_config_dsp_after_link_change(struct em_hw *hw, /* clear previous idle error counts */ ret_val = em_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; - for(i = 0; i < ffe_idle_err_timeout; i++) { + for (i = 0; i < ffe_idle_err_timeout; i++) { usec_delay(1000); ret_val = em_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - if(ret_val) + if (ret_val) return ret_val; idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT); - if(idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { + if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { hw->ffe_config_state = em_ffe_config_active; ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE, IGP01E1000_PHY_DSP_FFE_CM_CP); - if(ret_val) + if (ret_val) return ret_val; break; } - if(idle_errs) + if (idle_errs) ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_100; } } } } else { - if(hw->dsp_config_state == em_dsp_config_activated) { + if (hw->dsp_config_state == em_dsp_config_activated) { /* Save off the current value of register 0x2F5B to be restored at * the end of the routines. */ ret_val = em_read_phy_reg(hw, 0x2F5B, &phy_saved_data); - if(ret_val) + if (ret_val) return ret_val; /* Disable the PHY transmitter */ ret_val = em_write_phy_reg(hw, 0x2F5B, 0x0003); - if(ret_val) + if (ret_val) return ret_val; msec_delay_irq(20); ret_val = em_write_phy_reg(hw, 0x0000, IGP01E1000_IEEE_FORCE_GIGA); - if(ret_val) + if (ret_val) return ret_val; - for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { + for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { ret_val = em_read_phy_reg(hw, dsp_reg_array[i], &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS; ret_val = em_write_phy_reg(hw,dsp_reg_array[i], phy_data); - if(ret_val) + if (ret_val) return ret_val; } ret_val = em_write_phy_reg(hw, 0x0000, IGP01E1000_IEEE_RESTART_AUTONEG); - if(ret_val) + if (ret_val) return ret_val; msec_delay_irq(20); @@ -6468,40 +7104,40 @@ em_config_dsp_after_link_change(struct em_hw *hw, /* Now enable the transmitter */ ret_val = em_write_phy_reg(hw, 0x2F5B, phy_saved_data); - if(ret_val) + if (ret_val) return ret_val; hw->dsp_config_state = em_dsp_config_enabled; } - if(hw->ffe_config_state == em_ffe_config_active) { + if (hw->ffe_config_state == em_ffe_config_active) { /* Save off the current value of register 0x2F5B to be restored at * the end of the routines. */ ret_val = em_read_phy_reg(hw, 0x2F5B, &phy_saved_data); - if(ret_val) + if (ret_val) return ret_val; /* Disable the PHY transmitter */ ret_val = em_write_phy_reg(hw, 0x2F5B, 0x0003); - if(ret_val) + if (ret_val) return ret_val; msec_delay_irq(20); ret_val = em_write_phy_reg(hw, 0x0000, IGP01E1000_IEEE_FORCE_GIGA); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE, IGP01E1000_PHY_DSP_FFE_DEFAULT); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_write_phy_reg(hw, 0x0000, IGP01E1000_IEEE_RESTART_AUTONEG); - if(ret_val) + if (ret_val) return ret_val; msec_delay_irq(20); @@ -6509,7 +7145,7 @@ em_config_dsp_after_link_change(struct em_hw *hw, /* Now enable the transmitter */ ret_val = em_write_phy_reg(hw, 0x2F5B, phy_saved_data); - if(ret_val) + if (ret_val) return ret_val; hw->ffe_config_state = em_ffe_config_enabled; @@ -6534,20 +7170,20 @@ em_set_phy_mode(struct em_hw *hw) DEBUGFUNC("em_set_phy_mode"); - if((hw->mac_type == em_82545_rev_3) && - (hw->media_type == em_media_type_copper)) { + if ((hw->mac_type == em_82545_rev_3) && + (hw->media_type == em_media_type_copper)) { ret_val = em_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1, &eeprom_data); - if(ret_val) { + if (ret_val) { return ret_val; } - if((eeprom_data != EEPROM_RESERVED_WORD) && - (eeprom_data & EEPROM_PHY_CLASS_A)) { + if ((eeprom_data != EEPROM_RESERVED_WORD) && + (eeprom_data & EEPROM_PHY_CLASS_A)) { ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x000B); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x8104); - if(ret_val) + if (ret_val) return ret_val; hw->phy_reset_disable = FALSE; @@ -6575,39 +7211,51 @@ int32_t em_set_d3_lplu_state(struct em_hw *hw, boolean_t active) { + uint32_t phy_ctrl = 0; int32_t ret_val; uint16_t phy_data; DEBUGFUNC("em_set_d3_lplu_state"); - if(hw->phy_type != em_phy_igp && hw->phy_type != em_phy_igp_2) + if (hw->phy_type != em_phy_igp && hw->phy_type != em_phy_igp_2 + && hw->phy_type != em_phy_igp_3) return E1000_SUCCESS; /* During driver activity LPLU should not be used or it will attain link * from the lowest speeds starting from 10Mbps. The capability is used for * Dx transitions and states */ - if(hw->mac_type == em_82541_rev_2 || hw->mac_type == em_82547_rev_2) { + if (hw->mac_type == em_82541_rev_2 || hw->mac_type == em_82547_rev_2) { ret_val = em_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data); - if(ret_val) + if (ret_val) return ret_val; + } else if (hw->mac_type == em_ich8lan) { + /* MAC writes into PHY register based on the state transition + * and start auto-negotiation. SW driver can overwrite the settings + * in CSR PHY power control E1000_PHY_CTRL register. */ + phy_ctrl = E1000_READ_REG(hw, PHY_CTRL); } else { ret_val = em_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data); - if(ret_val) + if (ret_val) return ret_val; } - if(!active) { - if(hw->mac_type == em_82541_rev_2 || - hw->mac_type == em_82547_rev_2) { + if (!active) { + if (hw->mac_type == em_82541_rev_2 || + hw->mac_type == em_82547_rev_2) { phy_data &= ~IGP01E1000_GMII_FLEX_SPD; ret_val = em_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data); - if(ret_val) + if (ret_val) return ret_val; } else { + if (hw->mac_type == em_ich8lan) { + phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; + E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl); + } else { phy_data &= ~IGP02E1000_PM_D3_LPLU; ret_val = em_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); if (ret_val) return ret_val; + } } /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during @@ -6617,13 +7265,13 @@ em_set_d3_lplu_state(struct em_hw *hw, if (hw->smart_speed == em_smart_speed_on) { ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data); - if(ret_val) + if (ret_val) return ret_val; } else if (hw->smart_speed == em_smart_speed_off) { ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, @@ -6634,36 +7282,41 @@ em_set_d3_lplu_state(struct em_hw *hw, phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data); - if(ret_val) + if (ret_val) return ret_val; } - } else if((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) || - (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) || - (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) { + } else if ((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) || + (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) || + (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) { - if(hw->mac_type == em_82541_rev_2 || - hw->mac_type == em_82547_rev_2) { + if (hw->mac_type == em_82541_rev_2 || + hw->mac_type == em_82547_rev_2) { phy_data |= IGP01E1000_GMII_FLEX_SPD; ret_val = em_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data); - if(ret_val) + if (ret_val) return ret_val; } else { + if (hw->mac_type == em_ich8lan) { + phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; + E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl); + } else { phy_data |= IGP02E1000_PM_D3_LPLU; ret_val = em_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); if (ret_val) return ret_val; + } } /* When LPLU is enabled we should disable SmartSpeed */ ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data); - if(ret_val) + if (ret_val) return ret_val; } @@ -6688,22 +7341,32 @@ int32_t em_set_d0_lplu_state(struct em_hw *hw, boolean_t active) { + uint32_t phy_ctrl = 0; int32_t ret_val; uint16_t phy_data; DEBUGFUNC("em_set_d0_lplu_state"); - if(hw->mac_type <= em_82547_rev_2) + if (hw->mac_type <= em_82547_rev_2) return E1000_SUCCESS; + if (hw->mac_type == em_ich8lan) { + phy_ctrl = E1000_READ_REG(hw, PHY_CTRL); + } else { ret_val = em_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data); - if(ret_val) + if (ret_val) return ret_val; + } if (!active) { + if (hw->mac_type == em_ich8lan) { + phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; + E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl); + } else { phy_data &= ~IGP02E1000_PM_D0_LPLU; ret_val = em_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); if (ret_val) return ret_val; + } /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during * Dx states where the power conservation is most important. During @@ -6712,13 +7375,13 @@ em_set_d0_lplu_state(struct em_hw *hw, if (hw->smart_speed == em_smart_speed_on) { ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data); - if(ret_val) + if (ret_val) return ret_val; } else if (hw->smart_speed == em_smart_speed_off) { ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, @@ -6729,26 +7392,31 @@ em_set_d0_lplu_state(struct em_hw *hw, phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data); - if(ret_val) + if (ret_val) return ret_val; } } else { - - phy_data |= IGP02E1000_PM_D0_LPLU; + + if (hw->mac_type == em_ich8lan) { + phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; + E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl); + } else { + phy_data |= IGP02E1000_PM_D0_LPLU; ret_val = em_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); if (ret_val) return ret_val; + } /* When LPLU is enabled we should disable SmartSpeed */ ret_val = em_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data); - if(ret_val) + if (ret_val) return ret_val; } @@ -6769,7 +7437,7 @@ em_set_vco_speed(struct em_hw *hw) DEBUGFUNC("em_set_vco_speed"); - switch(hw->mac_type) { + switch (hw->mac_type) { case em_82545_rev_3: case em_82546_rev_3: break; @@ -6780,39 +7448,39 @@ em_set_vco_speed(struct em_hw *hw) /* Set PHY register 30, page 5, bit 8 to 0 */ ret_val = em_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data &= ~M88E1000_PHY_VCO_REG_BIT8; ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); - if(ret_val) + if (ret_val) return ret_val; /* Set PHY register 30, page 4, bit 11 to 1 */ ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); - if(ret_val) + if (ret_val) return ret_val; phy_data |= M88E1000_PHY_VCO_REG_BIT11; ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page); - if(ret_val) + if (ret_val) return ret_val; return E1000_SUCCESS; @@ -6828,7 +7496,7 @@ int32_t em_host_if_read_cookie(struct em_hw * hw, uint8_t *buffer) { uint8_t i; - uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET; + uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET; uint8_t length = E1000_MNG_DHCP_COOKIE_LENGTH; length = (length >> 2); @@ -6847,7 +7515,7 @@ em_host_if_read_cookie(struct em_hw * hw, uint8_t *buffer) * and also checks whether the previous command is completed. * It busy waits in case of previous command is not completed. * - * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or + * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or * timeout * - E1000_SUCCESS for success. ****************************************************************************/ @@ -6871,7 +7539,7 @@ em_mng_enable_host_if(struct em_hw * hw) msec_delay_irq(1); } - if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { + if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { DEBUGOUT("Previous command timeout failed .\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } @@ -6891,7 +7559,7 @@ em_mng_host_if_write(struct em_hw * hw, uint8_t *buffer, { uint8_t *tmp; uint8_t *bufptr = buffer; - uint32_t data; + uint32_t data = 0; uint16_t remaining, i, j, prev_bytes; /* sum = only sum of the data and it is not checksum */ @@ -6971,15 +7639,17 @@ em_mng_write_cmd_header(struct em_hw * hw, buffer = (uint8_t *) hdr; i = length; - while(i--) + while (i--) sum += buffer[i]; hdr->checksum = 0 - sum; length >>= 2; /* The device driver writes the relevant command block into the ram area. */ - for (i = 0; i < length; i++) + for (i = 0; i < length; i++) { E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((uint32_t *) hdr + i)); + E1000_WRITE_FLUSH(hw); + } return E1000_SUCCESS; } @@ -6992,8 +7662,7 @@ em_mng_write_cmd_header(struct em_hw * hw, * returns - E1000_SUCCESS for success. ****************************************************************************/ int32_t -em_mng_write_commit( - struct em_hw * hw) +em_mng_write_commit(struct em_hw * hw) { uint32_t hicr; @@ -7011,15 +7680,18 @@ em_mng_write_commit( * returns - TRUE when the mode is IAMT or FALSE. ****************************************************************************/ boolean_t -em_check_mng_mode( - struct em_hw *hw) +em_check_mng_mode(struct em_hw *hw) { uint32_t fwsm; fwsm = E1000_READ_REG(hw, FWSM); - if((fwsm & E1000_FWSM_MODE_MASK) == - (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)) + if (hw->mac_type == em_ich8lan) { + if ((fwsm & E1000_FWSM_MODE_MASK) == + (E1000_MNG_ICH_IAMT_MODE << E1000_FWSM_MODE_SHIFT)) + return TRUE; + } else if ((fwsm & E1000_FWSM_MODE_MASK) == + (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)) return TRUE; return FALSE; @@ -7162,31 +7834,31 @@ em_polarity_reversal_workaround(struct em_hw *hw) /* Disable the transmitter on the PHY */ ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); - if(ret_val) + if (ret_val) return ret_val; /* This loop will early-out if the NO link condition has been met. */ - for(i = PHY_FORCE_TIME; i > 0; i--) { + for (i = PHY_FORCE_TIME; i > 0; i--) { /* Read the MII Status Register and wait for Link Status bit * to be clear. */ ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if(ret_val) + if (ret_val) return ret_val; - if((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) break; + if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) break; msec_delay_irq(100); } @@ -7196,40 +7868,40 @@ em_polarity_reversal_workaround(struct em_hw *hw) /* Now we will re-enable the transmitter on the PHY */ ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); - if(ret_val) + if (ret_val) return ret_val; msec_delay_irq(50); ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0); - if(ret_val) + if (ret_val) return ret_val; msec_delay_irq(50); ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00); - if(ret_val) + if (ret_val) return ret_val; msec_delay_irq(50); ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); - if(ret_val) + if (ret_val) return ret_val; /* This loop will early-out if the link condition has been met. */ - for(i = PHY_FORCE_TIME; i > 0; i--) { + for (i = PHY_FORCE_TIME; i > 0; i--) { /* Read the MII Status Register and wait for Link Status bit * to be set. */ ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if(ret_val) + if (ret_val) return ret_val; ret_val = em_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if(ret_val) + if (ret_val) return ret_val; - if(mii_status_reg & MII_SR_LINK_STATUS) break; + if (mii_status_reg & MII_SR_LINK_STATUS) break; msec_delay_irq(100); } return E1000_SUCCESS; @@ -7306,15 +7978,15 @@ em_disable_pciex_master(struct em_hw *hw) em_set_pci_express_master_disable(hw); - while(timeout) { - if(!(E1000_READ_REG(hw, STATUS) & E1000_STATUS_GIO_MASTER_ENABLE)) + while (timeout) { + if (!(E1000_READ_REG(hw, STATUS) & E1000_STATUS_GIO_MASTER_ENABLE)) break; else usec_delay(100); timeout--; } - if(!timeout) { + if (!timeout) { DEBUGOUT("Master requests are pending.\n"); return -E1000_ERR_MASTER_REQUESTS_PENDING; } @@ -7347,13 +8019,15 @@ em_get_auto_rd_done(struct em_hw *hw) case em_82572: case em_82573: case em_80003es2lan: - while(timeout) { - if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break; + case em_ich8lan: + while (timeout) { + if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) + break; else msec_delay(1); timeout--; } - if(!timeout) { + if (!timeout) { DEBUGOUT("Auto read by HW from EEPROM has not completed.\n"); return -E1000_ERR_RESET; } @@ -7388,13 +8062,13 @@ em_get_phy_cfg_done(struct em_hw *hw) switch (hw->mac_type) { default: - msec_delay(10); + msec_delay_irq(10); break; case em_80003es2lan: /* Separate *_CFG_DONE_* bit for each port */ if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) cfg_mask = E1000_EEPROM_CFG_DONE_PORT_1; - /* Fall Through */ + /* FALLTHROUGH */ case em_82571: case em_82572: while (timeout) { @@ -7434,7 +8108,7 @@ em_get_hw_eeprom_semaphore(struct em_hw *hw) DEBUGFUNC("em_get_hw_eeprom_semaphore"); - if(!hw->eeprom_semaphore_present) + if (!hw->eeprom_semaphore_present) return E1000_SUCCESS; if (hw->mac_type == em_80003es2lan) { @@ -7445,20 +8119,20 @@ em_get_hw_eeprom_semaphore(struct em_hw *hw) /* Get the FW semaphore. */ timeout = hw->eeprom.word_size + 1; - while(timeout) { + while (timeout) { swsm = E1000_READ_REG(hw, SWSM); swsm |= E1000_SWSM_SWESMBI; E1000_WRITE_REG(hw, SWSM, swsm); /* if we managed to set the bit we got the semaphore. */ swsm = E1000_READ_REG(hw, SWSM); - if(swsm & E1000_SWSM_SWESMBI) + if (swsm & E1000_SWSM_SWESMBI) break; usec_delay(50); timeout--; } - if(!timeout) { + if (!timeout) { /* Release semaphores */ em_put_hw_eeprom_semaphore(hw); DEBUGOUT("Driver can't access the Eeprom - SWESMBI bit is set.\n"); @@ -7483,7 +8157,7 @@ em_put_hw_eeprom_semaphore(struct em_hw *hw) DEBUGFUNC("em_put_hw_eeprom_semaphore"); - if(!hw->eeprom_semaphore_present) + if (!hw->eeprom_semaphore_present) return; swsm = E1000_READ_REG(hw, SWSM); @@ -7516,16 +8190,16 @@ em_get_software_semaphore(struct em_hw *hw) if (hw->mac_type != em_80003es2lan) return E1000_SUCCESS; - while(timeout) { + while (timeout) { swsm = E1000_READ_REG(hw, SWSM); /* If SMBI bit cleared, it is now set and we hold the semaphore */ - if(!(swsm & E1000_SWSM_SMBI)) + if (!(swsm & E1000_SWSM_SMBI)) break; msec_delay_irq(1); timeout--; } - if(!timeout) { + if (!timeout) { DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); return -E1000_ERR_RESET; } @@ -7571,6 +8245,13 @@ int32_t em_check_phy_reset_block(struct em_hw *hw) { uint32_t manc = 0; + uint32_t fwsm = 0; + + if (hw->mac_type == em_ich8lan) { + fwsm = E1000_READ_REG(hw, FWSM); + return (fwsm & E1000_FWSM_RSPCIPHY) ? E1000_SUCCESS + : E1000_BLK_PHY_RESET; + } if (hw->mac_type > em_82547_rev_2) manc = E1000_READ_REG(hw, MANC); @@ -7594,11 +8275,854 @@ em_arc_subsystem_valid(struct em_hw *hw) case em_82573: case em_80003es2lan: fwsm = E1000_READ_REG(hw, FWSM); - if((fwsm & E1000_FWSM_MODE_MASK) != 0) + if ((fwsm & E1000_FWSM_MODE_MASK) != 0) return TRUE; break; + case em_ich8lan: + return TRUE; default: break; } return FALSE; } + + +/****************************************************************************** + * Configure PCI-Ex no-snoop + * + * hw - Struct containing variables accessed by shared code. + * no_snoop - Bitmap of no-snoop events. + * + * returns: E1000_SUCCESS + * + *****************************************************************************/ +int32_t +em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop) +{ + uint32_t gcr_reg = 0; + + DEBUGFUNC("em_set_pci_ex_no_snoop"); + + if (hw->bus_type == em_bus_type_unknown) + em_get_bus_info(hw); + + if (hw->bus_type != em_bus_type_pci_express) + return E1000_SUCCESS; + + if (no_snoop) { + gcr_reg = E1000_READ_REG(hw, GCR); + gcr_reg &= ~(PCI_EX_NO_SNOOP_ALL); + gcr_reg |= no_snoop; + E1000_WRITE_REG(hw, GCR, gcr_reg); + } + if (hw->mac_type == em_ich8lan) { + uint32_t ctrl_ext; + + E1000_WRITE_REG(hw, GCR, PCI_EX_82566_SNOOP_ALL); + + ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_RO_DIS; + E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + } + + return E1000_SUCCESS; +} + +/*************************************************************************** + * + * Get software semaphore FLAG bit (SWFLAG). + * SWFLAG is used to synchronize the access to all shared resource between + * SW, FW and HW. + * + * hw: Struct containing variables accessed by shared code + * + ***************************************************************************/ +int32_t +em_get_software_flag(struct em_hw *hw) +{ + int32_t timeout = PHY_CFG_TIMEOUT; + uint32_t extcnf_ctrl; + + DEBUGFUNC("em_get_software_flag"); + + if (hw->mac_type == em_ich8lan) { + while (timeout) { + extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL); + extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; + E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl); + + extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL); + if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) + break; + msec_delay_irq(1); + timeout--; + } + + if (!timeout) { + DEBUGOUT("FW or HW locks the resource too long.\n"); + return -E1000_ERR_CONFIG; + } + } + + return E1000_SUCCESS; +} + +/*************************************************************************** + * + * Release software semaphore FLAG bit (SWFLAG). + * SWFLAG is used to synchronize the access to all shared resource between + * SW, FW and HW. + * + * hw: Struct containing variables accessed by shared code + * + ***************************************************************************/ +void +em_release_software_flag(struct em_hw *hw) +{ + uint32_t extcnf_ctrl; + + DEBUGFUNC("em_release_software_flag"); + + if (hw->mac_type == em_ich8lan) { + extcnf_ctrl= E1000_READ_REG(hw, EXTCNF_CTRL); + extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; + E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl); + } + + return; +} + +/*************************************************************************** + * + * Disable dynamic power down mode in ife PHY. + * It can be used to workaround band-gap problem. + * + * hw: Struct containing variables accessed by shared code + * + ***************************************************************************/ +int32_t +em_ife_disable_dynamic_power_down(struct em_hw *hw) +{ + uint16_t phy_data; + int32_t ret_val = E1000_SUCCESS; + + DEBUGFUNC("em_ife_disable_dynamic_power_down"); + + if (hw->phy_type == em_phy_ife) { + ret_val = em_read_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, &phy_data); + if (ret_val) + return ret_val; + + phy_data |= IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN; + ret_val = em_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, phy_data); + } + + return ret_val; +} + +/*************************************************************************** + * + * Enable dynamic power down mode in ife PHY. + * It can be used to workaround band-gap problem. + * + * hw: Struct containing variables accessed by shared code + * + ***************************************************************************/ +int32_t +em_ife_enable_dynamic_power_down(struct em_hw *hw) +{ + uint16_t phy_data; + int32_t ret_val = E1000_SUCCESS; + + DEBUGFUNC("em_ife_enable_dynamic_power_down"); + + if (hw->phy_type == em_phy_ife) { + ret_val = em_read_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, &phy_data); + if (ret_val) + return ret_val; + + phy_data &= ~IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN; + ret_val = em_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, phy_data); + } + + return ret_val; +} + +/****************************************************************************** + * Reads a 16 bit word or words from the EEPROM using the ICH8's flash access + * register. + * + * hw - Struct containing variables accessed by shared code + * offset - offset of word in the EEPROM to read + * data - word read from the EEPROM + * words - number of words to read + *****************************************************************************/ +int32_t +em_read_eeprom_ich8(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; + uint16_t word = 0; + uint16_t i = 0; + + /* 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. + */ + /* Value of bit 22 corresponds to the flash bank we're on. */ + flash_bank = (E1000_READ_REG(hw, EECD) & E1000_EECD_SEC1VAL) ? 1 : 0; + + /* Adjust offset appropriately if we're on bank 1 - adjust for word size */ + bank_offset = flash_bank * (hw->flash_bank_size * 2); + + error = em_get_software_flag(hw); + if (error != E1000_SUCCESS) + return error; + + for (i = 0; i < words; i++) { + if (hw->eeprom_shadow_ram != NULL && + hw->eeprom_shadow_ram[offset+i].modified == TRUE) { + data[i] = hw->eeprom_shadow_ram[offset+i].eeprom_word; + } else { + /* The NVM part needs a byte offset, hence * 2 */ + act_offset = bank_offset + ((offset + i) * 2); + error = em_read_ich8_word(hw, act_offset, &word); + if (error != E1000_SUCCESS) + break; + data[i] = word; + } + } + + em_release_software_flag(hw); + + return error; +} + +/****************************************************************************** + * Writes a 16 bit word or words to the EEPROM using the ICH8's flash access + * register. Actually, writes are written to the shadow ram cache in the hw + * structure hw->em_shadow_ram. em_commit_shadow_ram flushes this to + * the NVM, which occurs when the NVM checksum is updated. + * + * hw - Struct containing variables accessed by shared code + * offset - offset of word in the EEPROM to write + * words - number of words to write + * data - words to write to the EEPROM + *****************************************************************************/ +int32_t +em_write_eeprom_ich8(struct em_hw *hw, uint16_t offset, uint16_t words, + uint16_t *data) +{ + uint32_t i = 0; + int32_t error = E1000_SUCCESS; + + error = em_get_software_flag(hw); + if (error != E1000_SUCCESS) + return error; + + /* A driver can write to the NVM only if it has eeprom_shadow_ram + * allocated. Subsequent reads to the modified words are read from + * this cached structure as well. Writes will only go into this + * cached structure unless it's followed by a call to + * em_update_eeprom_checksum() where it will commit the changes + * and clear the "modified" field. + */ + if (hw->eeprom_shadow_ram != NULL) { + for (i = 0; i < words; i++) { + if ((offset + i) < E1000_SHADOW_RAM_WORDS) { + hw->eeprom_shadow_ram[offset+i].modified = TRUE; + hw->eeprom_shadow_ram[offset+i].eeprom_word = data[i]; + } else { + error = -E1000_ERR_EEPROM; + break; + } + } + } else { + /* Drivers have the option to not allocate eeprom_shadow_ram as long + * as they don't perform any NVM writes. An attempt in doing so + * will result in this error. + */ + error = -E1000_ERR_EEPROM; + } + + em_release_software_flag(hw); + + return error; +} + +/****************************************************************************** + * This function does initial flash setup so that a new read/write/erase cycle + * can be started. + * + * hw - The pointer to the hw structure + ****************************************************************************/ +int32_t +em_ich8_cycle_init(struct em_hw *hw) +{ + union ich8_hws_flash_status hsfsts; + int32_t error = E1000_ERR_EEPROM; + int32_t i = 0; + + DEBUGFUNC("em_ich8_cycle_init"); + + hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + + /* May be check the Flash Des Valid bit in Hw status */ + if (hsfsts.hsf_status.fldesvalid == 0) { + DEBUGOUT("Flash descriptor invalid. SW Sequencing must be used."); + return error; + } + + /* Clear FCERR in Hw status by writing 1 */ + /* Clear DAEL in Hw status by writing a 1 */ + hsfsts.hsf_status.flcerr = 1; + hsfsts.hsf_status.dael = 1; + + E1000_WRITE_ICH8_REG16(hw, ICH8_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 be changed + * in the hardware so that it is 1 after harware reset, which can then be + * used as an indication whether a cycle is in progress or has been + * completed .. we should also have some software semaphore mechanism to + * guard FDONE or the cycle in progress bit so that two threads access to + * those bits can be sequentiallized or a way so that 2 threads dont + * start the cycle at the same time */ + + if (hsfsts.hsf_status.flcinprog == 0) { + /* There is no cycle running at present, so we can start a cycle */ + /* Begin by setting Flash Cycle Done. */ + hsfsts.hsf_status.flcdone = 1; + E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval); + error = E1000_SUCCESS; + } else { + /* otherwise poll for sometime so the current cycle has a chance + * to end before giving up. */ + for (i = 0; i < ICH8_FLASH_COMMAND_TIMEOUT; i++) { + hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcinprog == 0) { + error = E1000_SUCCESS; + break; + } + usec_delay(1); + } + if (error == E1000_SUCCESS) { + /* Successful in waiting for previous cycle to timeout, + * now set the Flash Cycle Done. */ + hsfsts.hsf_status.flcdone = 1; + E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval); + } else { + DEBUGOUT("Flash controller busy, cannot get access"); + } + } + return error; +} + +/****************************************************************************** + * This function starts a flash cycle and waits for its completion + * + * hw - The pointer to the hw structure + ****************************************************************************/ +int32_t +em_ich8_flash_cycle(struct em_hw *hw, uint32_t timeout) +{ + union ich8_hws_flash_ctrl hsflctl; + 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_ICH8_REG16(hw, ICH8_FLASH_HSFCTL); + hsflctl.hsf_ctrl.flcgo = 1; + E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval); + + /* wait till FDONE bit is set to 1 */ + do { + hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcdone == 1) + break; + usec_delay(1); + i++; + } while (i < timeout); + if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0) { + error = E1000_SUCCESS; + } + return error; +} + +/****************************************************************************** + * Reads a byte or word from the NVM using the ICH8 flash access registers. + * + * hw - The pointer to the hw structure + * index - The index of the byte or word to read. + * size - Size of data to read, 1=byte 2=word + * data - Pointer to the word to store the value read. + *****************************************************************************/ +int32_t +em_read_ich8_data(struct em_hw *hw, uint32_t index, + uint32_t size, uint16_t* data) +{ + union ich8_hws_flash_status hsfsts; + union ich8_hws_flash_ctrl hsflctl; + uint32_t flash_linear_address; + uint32_t flash_data = 0; + int32_t error = -E1000_ERR_EEPROM; + int32_t count = 0; + + DEBUGFUNC("em_read_ich8_data"); + + if (size < 1 || size > 2 || data == 0x0 || + index > ICH8_FLASH_LINEAR_ADDR_MASK) + return error; + + flash_linear_address = (ICH8_FLASH_LINEAR_ADDR_MASK & index) + + hw->flash_base_addr; + + do { + usec_delay(1); + /* Steps */ + error = em_ich8_cycle_init(hw); + if (error != E1000_SUCCESS) + break; + + hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL); + /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ + hsflctl.hsf_ctrl.fldbcount = size - 1; + hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_READ; + E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval); + + /* Write the last 24 bits of index into Flash Linear address field in + * Flash Address */ + /* TODO: TBD maybe check the index against the size of flash */ + + E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address); + + error = em_ich8_flash_cycle(hw, ICH8_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) { + flash_data = E1000_READ_ICH8_REG(hw, ICH8_FLASH_FDATA0); + if (size == 1) { + *data = (uint8_t)(flash_data & 0x000000FF); + } else if (size == 2) { + *data = (uint16_t)(flash_data & 0x0000FFFF); + } + 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...ICH8_FLASH_CYCLE_REPEAT_COUNT times. + */ + hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_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++ < ICH8_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. + * size - Size of data to read, 1=byte 2=word + * data - The byte(s) to write to the NVM. + *****************************************************************************/ +int32_t +em_write_ich8_data(struct em_hw *hw, uint32_t index, uint32_t size, + uint16_t data) +{ + union ich8_hws_flash_status hsfsts; + union ich8_hws_flash_ctrl hsflctl; + uint32_t flash_linear_address; + uint32_t flash_data = 0; + int32_t error = -E1000_ERR_EEPROM; + int32_t count = 0; + + DEBUGFUNC("em_write_ich8_data"); + + if (size < 1 || size > 2 || data > size * 0xff || + index > ICH8_FLASH_LINEAR_ADDR_MASK) + return error; + + flash_linear_address = (ICH8_FLASH_LINEAR_ADDR_MASK & index) + + hw->flash_base_addr; + + do { + usec_delay(1); + /* Steps */ + error = em_ich8_cycle_init(hw); + if (error != E1000_SUCCESS) + break; + + hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL); + /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ + hsflctl.hsf_ctrl.fldbcount = size -1; + hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_WRITE; + E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval); + + /* Write the last 24 bits of index into Flash Linear address field in + * Flash Address */ + E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address); + + if (size == 1) + flash_data = (uint32_t)data & 0x00FF; + else + flash_data = (uint32_t)data; + + E1000_WRITE_ICH8_REG(hw, ICH8_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 */ + error = em_ich8_flash_cycle(hw, ICH8_FLASH_COMMAND_TIMEOUT); + if (error == E1000_SUCCESS) { + break; + } else { + /* 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...ICH8_FLASH_CYCLE_REPEAT_COUNT times. + */ + hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_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++ < ICH8_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 + * index - The index of the byte to read. + * data - Pointer to a byte to store the value read. + *****************************************************************************/ +int32_t +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 (status == E1000_SUCCESS) { + *data = (uint8_t)word; + } + + return status; +} + +/****************************************************************************** + * Writes a single byte 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 index of the byte to write. + * byte - The byte to write to the NVM. + *****************************************************************************/ +int32_t +em_verify_write_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t byte) +{ + int32_t error = E1000_SUCCESS; + int32_t program_retries; + uint8_t temp_byte; + + em_write_ich8_byte(hw, index, byte); + usec_delay(100); + + for (program_retries = 0; program_retries < 100; program_retries++) { + em_read_ich8_byte(hw, index, &temp_byte); + if (temp_byte == byte) + break; + usec_delay(10); + em_write_ich8_byte(hw, index, byte); + usec_delay(100); + } + 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 + * index - The index of the byte to read. + * data - The byte to write to the NVM. + *****************************************************************************/ +int32_t +em_write_ich8_byte(struct em_hw *hw, uint32_t index, uint8_t data) +{ + int32_t status = E1000_SUCCESS; + uint16_t word = (uint16_t)data; + + status = em_write_ich8_data(hw, index, 1, word); + + return status; +} + +/****************************************************************************** + * Reads a word 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. + *****************************************************************************/ +int32_t +em_read_ich8_word(struct em_hw *hw, uint32_t index, uint16_t *data) +{ + int32_t status = E1000_SUCCESS; + status = em_read_ich8_data(hw, index, 2, data); + return status; +} + +/****************************************************************************** + * Writes a word to 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 - The word to write to the NVM. + *****************************************************************************/ +int32_t +em_write_ich8_word(struct em_hw *hw, uint32_t index, uint16_t data) +{ + int32_t status = E1000_SUCCESS; + status = em_write_ich8_data(hw, index, 2, data); + return status; +} + +/****************************************************************************** + * Erases the bank specified. Each bank is a 4k block. Segments are 0 based. + * segment N is 4096 * N + flash_reg_addr. + * + * hw - pointer to em_hw structure + * segment - 0 for first segment, 1 for second segment, etc. + *****************************************************************************/ +int32_t +em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t segment) +{ + union ich8_hws_flash_status hsfsts; + union ich8_hws_flash_ctrl hsflctl; + uint32_t flash_linear_address; + int32_t count = 0; + int32_t error = E1000_ERR_EEPROM; + int32_t iteration, seg_size; + int32_t sector_size; + int32_t j = 0; + int32_t error_flag = 0; + + hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + + /* Determine HW Sector size: Read BERASE bits of Hw flash Status register */ + /* 00: The Hw sector is 256 bytes, hence we need to erase 16 + * consecutive sectors. The start index for the nth Hw sector can be + * calculated as = segment * 4096 + n * 256 + * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector. + * The start index for the nth Hw sector can be calculated + * as = segment * 4096 + * 10: Error condition + * 11: The Hw sector size is much bigger than the size asked to + * erase...error condition */ + if (hsfsts.hsf_status.berasesz == 0x0) { + /* Hw sector size 256 */ + sector_size = seg_size = ICH8_FLASH_SEG_SIZE_256; + iteration = ICH8_FLASH_SECTOR_SIZE / ICH8_FLASH_SEG_SIZE_256; + } else if (hsfsts.hsf_status.berasesz == 0x1) { + sector_size = seg_size = ICH8_FLASH_SEG_SIZE_4K; + iteration = 1; + } else if (hsfsts.hsf_status.berasesz == 0x3) { + sector_size = seg_size = ICH8_FLASH_SEG_SIZE_64K; + iteration = 1; + } else { + return error; + } + + for (j = 0; j < iteration ; j++) { + do { + count++; + /* Steps */ + error = em_ich8_cycle_init(hw); + if (error != E1000_SUCCESS) { + error_flag = 1; + break; + } + + /* Write a value 11 (block Erase) in Flash Cycle field in Hw flash + * Control */ + hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL); + hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_ERASE; + E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval); + + /* Write the last 24 bits of an index within the block into Flash + * Linear address field in Flash Address. This probably needs to + * be calculated here based off the on-chip segment size and the + * software segment size assumed (4K) */ + /* TBD */ + flash_linear_address = segment * sector_size + j * seg_size; + flash_linear_address &= ICH8_FLASH_LINEAR_ADDR_MASK; + flash_linear_address += hw->flash_base_addr; + + E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address); + + error = em_ich8_flash_cycle(hw, 1000000); + /* Check if FCERR is set to 1. If 1, clear it and try the whole + * sequence a few more times else Done */ + if (error == E1000_SUCCESS) { + break; + } else { + hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcerr == 1) { + /* repeat for some time before giving up */ + continue; + } else if (hsfsts.hsf_status.flcdone == 0) { + error_flag = 1; + break; + } + } + } while ((count < ICH8_FLASH_CYCLE_REPEAT_COUNT) && !error_flag); + if (error_flag == 1) + break; + } + if (error_flag != 1) + error = E1000_SUCCESS; + return error; +} + +/****************************************************************************** + * + * Reverse duplex setting without breaking the link. + * + * hw: Struct containing variables accessed by shared code + * + *****************************************************************************/ +int32_t +em_duplex_reversal(struct em_hw *hw) +{ + int32_t ret_val; + uint16_t phy_data; + + if (hw->phy_type != em_phy_igp_3) + return E1000_SUCCESS; + + ret_val = em_read_phy_reg(hw, PHY_CTRL, &phy_data); + if (ret_val) + return ret_val; + + phy_data ^= MII_CR_FULL_DUPLEX; + + ret_val = em_write_phy_reg(hw, PHY_CTRL, phy_data); + if (ret_val) + return ret_val; + + ret_val = em_read_phy_reg(hw, IGP3E1000_PHY_MISC_CTRL, &phy_data); + if (ret_val) + return ret_val; + + phy_data |= IGP3_PHY_MISC_DUPLEX_MANUAL_SET; + ret_val = em_write_phy_reg(hw, IGP3E1000_PHY_MISC_CTRL, phy_data); + + return ret_val; +} + +int32_t +em_init_lcd_from_nvm_config_region(struct em_hw *hw, + uint32_t cnf_base_addr, uint32_t cnf_size) +{ + uint32_t ret_val = E1000_SUCCESS; + uint16_t word_addr, reg_data, reg_addr; + uint16_t i; + + /* cnf_base_addr is in DWORD */ + word_addr = (uint16_t)(cnf_base_addr << 1); + + /* cnf_size is returned in size of dwords */ + for (i = 0; i < cnf_size; i++) { + ret_val = em_read_eeprom(hw, (word_addr + i*2), 1, ®_data); + if (ret_val) + return ret_val; + + ret_val = em_read_eeprom(hw, (word_addr + i*2 + 1), 1, ®_addr); + if (ret_val) + return ret_val; + + ret_val = em_get_software_flag(hw); + if (ret_val != E1000_SUCCESS) + return ret_val; + + ret_val = em_write_phy_reg_ex(hw, (uint32_t)reg_addr, reg_data); + + em_release_software_flag(hw); + } + + return ret_val; +} + +int32_t +em_init_lcd_from_nvm(struct em_hw *hw) +{ + uint32_t reg_data, cnf_base_addr, cnf_size, ret_val, loop; + + if (hw->phy_type != em_phy_igp_3) + return E1000_SUCCESS; + + /* Check if SW needs configure the PHY */ + reg_data = E1000_READ_REG(hw, FEXTNVM); + if (!(reg_data & FEXTNVM_SW_CONFIG)) + return E1000_SUCCESS; + + /* Wait for basic configuration completes before proceeding*/ + loop = 0; + do { + reg_data = E1000_READ_REG(hw, STATUS) & E1000_STATUS_LAN_INIT_DONE; + usec_delay(100); + loop++; + } while ((!reg_data) && (loop < 50)); + + /* Clear the Init Done bit for the next init event */ + reg_data = E1000_READ_REG(hw, STATUS); + reg_data &= ~E1000_STATUS_LAN_INIT_DONE; + E1000_WRITE_REG(hw, STATUS, reg_data); + + /* Make sure HW does not configure LCD from PHY extended configuration + before SW configuration */ + reg_data = E1000_READ_REG(hw, EXTCNF_CTRL); + if ((reg_data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) == 0x0000) { + reg_data = E1000_READ_REG(hw, EXTCNF_SIZE); + cnf_size = reg_data & E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH; + cnf_size >>= 16; + if (cnf_size) { + reg_data = E1000_READ_REG(hw, EXTCNF_CTRL); + cnf_base_addr = reg_data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER; + /* cnf_base_addr is in DWORD */ + cnf_base_addr >>= 16; + + /* Configure LCD from extended configuration region. */ + ret_val = em_init_lcd_from_nvm_config_region(hw, cnf_base_addr, + cnf_size); + if (ret_val) + return ret_val; + } + } + + return E1000_SUCCESS; +} diff --git a/sys/dev/pci/if_em_hw.h b/sys/dev/pci/if_em_hw.h index 70a0dbe840e..9843e3fe95b 100644 --- a/sys/dev/pci/if_em_hw.h +++ b/sys/dev/pci/if_em_hw.h @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ -/* $OpenBSD: if_em_hw.h,v 1.16 2006/07/05 01:15:30 brad Exp $ */ +/* $OpenBSD: if_em_hw.h,v 1.17 2006/07/07 02:56:18 brad Exp $ */ /* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */ /* if_em_hw.h @@ -68,6 +68,7 @@ typedef enum { em_82572, em_82573, em_80003es2lan, + em_ich8lan, em_num_macs } em_mac_type; @@ -76,6 +77,7 @@ typedef enum { em_eeprom_spi, em_eeprom_microwire, em_eeprom_flash, + em_eeprom_ich8, em_eeprom_none, /* No NVM support */ em_num_eeprom_types } em_eeprom_type; @@ -104,6 +106,11 @@ typedef enum { em_fc_default = 0xFF } em_fc_type; +struct em_shadow_ram { + uint16_t eeprom_word; + boolean_t modified; +}; + /* PCI bus types */ typedef enum { em_bus_type_unknown = 0, @@ -224,6 +231,8 @@ typedef enum { em_phy_igp, em_phy_igp_2, em_phy_gg82563, + em_phy_igp_3, + em_phy_ife, em_phy_undefined = 0xFF } em_phy_type; @@ -320,6 +329,11 @@ int32_t em_read_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t *phy_data) int32_t em_write_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t data); int32_t em_phy_hw_reset(struct em_hw *hw); int32_t em_phy_reset(struct em_hw *hw); +void em_phy_powerdown_workaround(struct em_hw *hw); +int32_t em_kumeran_lock_loss_workaround(struct em_hw *hw); +int32_t em_duplex_reversal(struct em_hw *hw); +int32_t em_init_lcd_from_nvm_config_region(struct em_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size); +int32_t em_init_lcd_from_nvm(struct em_hw *hw); int32_t em_detect_gig_phy(struct em_hw *hw); int32_t em_phy_get_info(struct em_hw *hw, struct em_phy_info *phy_info); int32_t em_phy_m88_get_info(struct em_hw *hw, struct em_phy_info *phy_info); @@ -330,7 +344,6 @@ int32_t em_check_downshift(struct em_hw *hw); int32_t em_validate_mdi_setting(struct em_hw *hw); int32_t em_read_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t *data); int32_t em_write_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t data); -int32_t em_duplex_reversal(struct em_hw *hw); /* EEPROM Functions */ int32_t em_init_eeprom_params(struct em_hw *hw); @@ -346,9 +359,10 @@ uint32_t em_enable_mng_pass_thru(struct em_hw *hw); #define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 /* Host Interface data length */ #define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 /* Time in ms to process MNG command */ -#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 /* Cookie offset */ -#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 /* Cookie length */ -#define E1000_MNG_IAMT_MODE 0x3 +#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 /* Cookie offset */ +#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 /* Cookie length */ +#define E1000_MNG_IAMT_MODE 0x3 +#define E1000_MNG_ICH_IAMT_MODE 0x2 #define E1000_IAMT_SIGNATURE 0x544D4149 /* Intel(R) Active Management Technology signature */ #define E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT 0x1 /* DHCP parsing enabled */ @@ -380,15 +394,15 @@ struct em_host_mng_dhcp_cookie{ uint8_t checksum; }; -int32_t em_mng_write_dhcp_info(struct em_hw *hw, uint8_t *buffer, - uint16_t length); +int32_t em_mng_write_dhcp_info(struct em_hw *hw, uint8_t *buffer, + uint16_t length); boolean_t em_check_mng_mode(struct em_hw *hw); boolean_t em_enable_tx_pkt_filtering(struct em_hw *hw); int32_t em_mng_enable_host_if(struct em_hw *hw); int32_t em_mng_host_if_write(struct em_hw *hw, uint8_t *buffer, uint16_t length, uint16_t offset, uint8_t *sum); -int32_t em_mng_write_cmd_header(struct em_hw* hw, - struct em_host_mng_command_header* hdr); +int32_t em_mng_write_cmd_header(struct em_hw *hw, + struct em_host_mng_command_header *hdr); int32_t em_mng_write_commit(struct em_hw *hw); @@ -397,16 +411,19 @@ int32_t em_validate_eeprom_checksum(struct em_hw *hw); int32_t em_update_eeprom_checksum(struct em_hw *hw); int32_t em_write_eeprom(struct em_hw *hw, uint16_t reg, uint16_t words, uint16_t *data); int32_t em_read_part_num(struct em_hw *hw, uint32_t * part_num); -int32_t em_read_mac_addr(struct em_hw * hw); +int32_t em_read_mac_addr(struct em_hw *hw); int32_t em_swfw_sync_acquire(struct em_hw *hw, uint16_t mask); void em_swfw_sync_release(struct em_hw *hw, uint16_t mask); +void em_release_software_flag(struct em_hw *hw); +int32_t em_get_software_flag(struct em_hw *hw); /* Filters (multicast, vlan, receive) */ void em_init_rx_addrs(struct em_hw *hw); -void em_mc_addr_list_update(struct em_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count); -uint32_t em_hash_mc_addr(struct em_hw *hw, uint8_t * mc_addr); +void em_mc_addr_list_update(struct em_hw *hw, uint8_t *mc_addr_list, uint32_t mc_addr_count, + uint32_t pad, uint32_t rar_used_count); +uint32_t em_hash_mc_addr(struct em_hw *hw, uint8_t *mc_addr); void em_mta_set(struct em_hw *hw, uint32_t hash_value); -void em_rar_set(struct em_hw *hw, uint8_t * mc_addr, uint32_t rar_index); +void em_rar_set(struct em_hw *hw, uint8_t *mc_addr, uint32_t rar_index); void em_write_vfta(struct em_hw *hw, uint32_t offset, uint32_t value); void em_clear_vfta(struct em_hw *hw); @@ -415,6 +432,7 @@ int32_t em_setup_led(struct em_hw *hw); int32_t em_cleanup_led(struct em_hw *hw); int32_t em_led_on(struct em_hw *hw); int32_t em_led_off(struct em_hw *hw); +int32_t em_blink_led_start(struct em_hw *hw); /* Adaptive IFS Functions */ @@ -422,12 +440,12 @@ int32_t em_led_off(struct em_hw *hw); void em_clear_hw_cntrs(struct em_hw *hw); void em_reset_adaptive(struct em_hw *hw); void em_update_adaptive(struct em_hw *hw); -void em_tbi_adjust_stats(struct em_hw *hw, struct em_hw_stats *stats, uint32_t frame_len, uint8_t * mac_addr); +void em_tbi_adjust_stats(struct em_hw *hw, struct em_hw_stats *stats, uint32_t frame_len, uint8_t *mac_addr); void em_get_bus_info(struct em_hw *hw); void em_pci_set_mwi(struct em_hw *hw); void em_pci_clear_mwi(struct em_hw *hw); -void em_read_pci_cfg(struct em_hw *hw, uint32_t reg, uint16_t * value); -void em_write_pci_cfg(struct em_hw *hw, uint32_t reg, uint16_t * value); +void em_read_pci_cfg(struct em_hw *hw, uint32_t reg, uint16_t *value); +void em_write_pci_cfg(struct em_hw *hw, uint32_t reg, uint16_t *value); /* Port I/O is only supported on 82544 and newer */ uint32_t em_read_reg_io(struct em_hw *hw, uint32_t offset); void em_write_reg_io(struct em_hw *hw, uint32_t offset, uint32_t value); @@ -448,6 +466,32 @@ int32_t em_commit_shadow_ram(struct em_hw *hw); uint8_t em_arc_subsystem_valid(struct em_hw *hw); int32_t em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop); +int32_t em_read_ich8_byte(struct em_hw *hw, uint32_t index, + uint8_t *data); +int32_t em_verify_write_ich8_byte(struct em_hw *hw, uint32_t index, + uint8_t byte); +int32_t em_write_ich8_byte(struct em_hw *hw, uint32_t index, + uint8_t byte); +int32_t em_read_ich8_word(struct em_hw *hw, uint32_t index, + uint16_t *data); +int32_t em_write_ich8_word(struct em_hw *hw, uint32_t index, + uint16_t word); +int32_t em_read_ich8_data(struct em_hw *hw, uint32_t index, + uint32_t size, uint16_t *data); +int32_t em_write_ich8_data(struct em_hw *hw, uint32_t index, + uint32_t size, uint16_t data); +int32_t em_read_eeprom_ich8(struct em_hw *hw, uint16_t offset, + uint16_t words, uint16_t *data); +int32_t em_write_eeprom_ich8(struct em_hw *hw, uint16_t offset, + uint16_t words, uint16_t *data); +int32_t em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t segment); +int32_t em_ich8_cycle_init(struct em_hw *hw); +int32_t em_ich8_flash_cycle(struct em_hw *hw, uint32_t timeout); +int32_t em_phy_ife_get_info(struct em_hw *hw, + struct em_phy_info *phy_info); +int32_t em_ife_disable_dynamic_power_down(struct em_hw *hw); +int32_t em_ife_enable_dynamic_power_down(struct em_hw *hw); + #ifndef E1000_READ_REG_IO #define E1000_READ_REG_IO(a, reg) \ em_read_reg_io((a), E1000_##reg) @@ -464,7 +508,6 @@ int32_t em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop); #define E1000_DEV_ID_82544GC_COPPER 0x100C #define E1000_DEV_ID_82544GC_LOM 0x100D #define E1000_DEV_ID_82540EM 0x100E -#define E1000_DEV_ID_82541ER_LOM 0x1014 #define E1000_DEV_ID_82540EM_LOM 0x1015 #define E1000_DEV_ID_82540EP_LOM 0x1016 #define E1000_DEV_ID_82540EP 0x1017 @@ -479,6 +522,7 @@ int32_t em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop); #define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D #define E1000_DEV_ID_82541EI 0x1013 #define E1000_DEV_ID_82541EI_MOBILE 0x1018 +#define E1000_DEV_ID_82541ER_LOM 0x1014 #define E1000_DEV_ID_82541ER 0x1078 #define E1000_DEV_ID_82547GI 0x1075 #define E1000_DEV_ID_82541GI 0x1076 @@ -512,6 +556,14 @@ int32_t em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop); #define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5 #define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 #define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 +#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA +#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB + +#define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049 +#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A +#define E1000_DEV_ID_ICH8_IGP_C 0x104B +#define E1000_DEV_ID_ICH8_IFE 0x104C +#define E1000_DEV_ID_ICH8_IGP_M 0x104D #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 @@ -545,7 +597,7 @@ int32_t em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop); #define MAX_JUMBO_FRAME_SIZE 0x3F00 /* 802.1q VLAN Packet Sizes */ -#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMAed) */ +#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMAed) */ /* Ethertype field values */ #define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */ @@ -571,6 +623,7 @@ int32_t em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop); * o TXDW = Transmit Descriptor Written Back * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) * o RXSEQ = Receive Sequence Error + * o RXO = Receive Overrun * o LSC = Link Status Change */ #define IMS_ENABLE_MASK ( \ @@ -581,12 +634,22 @@ int32_t em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop); E1000_IMS_RXO | \ E1000_IMS_LSC) +/* Additional interrupts need to be handled for em_ich8lan: + DSW = The FW changed the status of the DISSW bit in FWSM + PHYINT = The LAN connected device generates an interrupt + EPRST = Manageability reset event */ +#define IMS_ICH8LAN_ENABLE_MASK (\ + E1000_IMS_DSW | \ + E1000_IMS_PHYINT | \ + E1000_IMS_EPRST) + /* Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. We * reserve one of these spots for our directed address, allowing us room for * E1000_RAR_ENTRIES - 1 multicast addresses. */ #define E1000_RAR_ENTRIES 15 +#define E1000_RAR_ENTRIES_ICH8LAN 7 #define MIN_NUMBER_OF_DESCRIPTORS 8 #define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8 @@ -807,6 +870,9 @@ struct em_data_desc { #define E1000_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */ #define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ +#define E1000_NUM_UNICAST_ICH8LAN 7 +#define E1000_MC_TBL_SIZE_ICH8LAN 32 + /* Receive Address Register */ struct em_rar { volatile uint32_t low; /* receive address low */ @@ -815,6 +881,7 @@ struct em_rar { /* Number of entries in the Multicast Table Array (MTA). */ #define E1000_NUM_MTA_REGISTERS 128 +#define E1000_NUM_MTA_REGISTERS_ICH8LAN 32 /* IPv4 Address Table Entry */ struct em_ipv4_at_entry { @@ -825,6 +892,7 @@ struct em_ipv4_at_entry { /* Four wakeup IP addresses are supported */ #define E1000_WAKEUP_IP_ADDRESS_COUNT_MAX 4 #define E1000_IP4AT_SIZE E1000_WAKEUP_IP_ADDRESS_COUNT_MAX +#define E1000_IP4AT_SIZE_ICH8LAN 3 #define E1000_IP6AT_SIZE 1 /* IPv6 Address Table Entry */ @@ -883,6 +951,7 @@ struct em_ffvt_entry { #define E1000_FLA 0x0001C /* Flash Access - RW */ #define E1000_MDIC 0x00020 /* MDI Control - RW */ #define E1000_SCTL 0x00024 /* SerDes Control - RW */ +#define E1000_FEXTNVM 0x00028 /* Future Extended NVM register */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ #define E1000_FCT 0x00030 /* Flow Control Type - RW */ @@ -911,6 +980,8 @@ struct em_ffvt_entry { #define E1000_LEDCTL 0x00E00 /* LED Control - RW */ #define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */ #define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */ +#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */ +#define FEXTNVM_SW_CONFIG 0x0001 #define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ #define E1000_PBS 0x01008 /* Packet Buffer Size */ #define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ @@ -938,11 +1009,13 @@ struct em_ffvt_entry { #define E1000_RDH0 E1000_RDH /* RX Desc Head (0) - RW */ #define E1000_RDT0 E1000_RDT /* RX Desc Tail (0) - RW */ #define E1000_RDTR0 E1000_RDTR /* RX Delay Timer (0) - RW */ -#define E1000_RXDCTL 0x02828 /* RX Descriptor Control - RW */ +#define E1000_RXDCTL 0x02828 /* RX Descriptor Control queue 0 - RW */ +#define E1000_RXDCTL1 0x02928 /* RX Descriptor Control queue 1 - RW */ #define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */ #define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */ #define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */ #define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */ +#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */ #define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */ #define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */ #define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */ @@ -1089,6 +1162,7 @@ struct em_ffvt_entry { #define E1000_82542_FLA E1000_FLA #define E1000_82542_MDIC E1000_MDIC #define E1000_82542_SCTL E1000_SCTL +#define E1000_82542_FEXTNVM E1000_FEXTNVM #define E1000_82542_FCAL E1000_FCAL #define E1000_82542_FCAH E1000_FCAH #define E1000_82542_FCT E1000_FCT @@ -1112,6 +1186,19 @@ struct em_ffvt_entry { #define E1000_82542_RDLEN0 E1000_82542_RDLEN #define E1000_82542_RDH0 E1000_82542_RDH #define E1000_82542_RDT0 E1000_82542_RDT +#define E1000_82542_SRRCTL(_n) (0x280C + ((_n) << 8)) /* Split and Replication + * RX Control - RW */ +#define E1000_82542_DCA_RXCTRL(_n) (0x02814 + ((_n) << 8)) +#define E1000_82542_RDBAH3 0x02B04 /* RX Desc Base High Queue 3 - RW */ +#define E1000_82542_RDBAL3 0x02B00 /* RX Desc Low Queue 3 - RW */ +#define E1000_82542_RDLEN3 0x02B08 /* RX Desc Length Queue 3 - RW */ +#define E1000_82542_RDH3 0x02B10 /* RX Desc Head Queue 3 - RW */ +#define E1000_82542_RDT3 0x02B18 /* RX Desc Tail Queue 3 - RW */ +#define E1000_82542_RDBAL2 0x02A00 /* RX Desc Base Low Queue 2 - RW */ +#define E1000_82542_RDBAH2 0x02A04 /* RX Desc Base High Queue 2 - RW */ +#define E1000_82542_RDLEN2 0x02A08 /* RX Desc Length Queue 2 - RW */ +#define E1000_82542_RDH2 0x02A10 /* RX Desc Head Queue 2 - RW */ +#define E1000_82542_RDT2 0x02A18 /* RX Desc Tail Queue 2 - RW */ #define E1000_82542_RDTR1 0x00130 #define E1000_82542_RDBAL1 0x00138 #define E1000_82542_RDBAH1 0x0013C @@ -1149,11 +1236,14 @@ struct em_ffvt_entry { #define E1000_82542_FLOP E1000_FLOP #define E1000_82542_EXTCNF_CTRL E1000_EXTCNF_CTRL #define E1000_82542_EXTCNF_SIZE E1000_EXTCNF_SIZE +#define E1000_82542_PHY_CTRL E1000_PHY_CTRL #define E1000_82542_ERT E1000_ERT #define E1000_82542_RXDCTL E1000_RXDCTL +#define E1000_82542_RXDCTL1 E1000_RXDCTL1 #define E1000_82542_RADV E1000_RADV #define E1000_82542_RSRPD E1000_RSRPD #define E1000_82542_TXDMAC E1000_TXDMAC +#define E1000_82542_KABGTXD E1000_KABGTXD #define E1000_82542_TDFHS E1000_TDFHS #define E1000_82542_TDFTS E1000_TDFTS #define E1000_82542_TDFPC E1000_TDFPC @@ -1356,6 +1446,9 @@ struct em_hw { uint32_t phy_init_script; em_media_type media_type; void *back; + struct em_shadow_ram *eeprom_shadow_ram; + uint32_t flash_bank_size; + uint32_t flash_base_addr; em_fc_type fc; em_bus_speed bus_speed; em_bus_width bus_width; @@ -1367,6 +1460,7 @@ struct em_hw { uint32_t asf_firmware_present; uint32_t eeprom_semaphore_present; uint32_t swfw_sync_present; + uint32_t swfwhw_semaphore_present; unsigned long io_base; uint32_t phy_id; uint32_t phy_revision; @@ -1426,6 +1520,7 @@ struct em_hw { boolean_t in_ifs_mode; boolean_t mng_reg_access_disabled; boolean_t leave_av_bit_off; + boolean_t kmrn_lock_loss_workaround_disabled; }; #define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */ @@ -1473,6 +1568,7 @@ struct em_hw { #define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */ #define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ #define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ +#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to manageability engine */ /* Device Status */ #define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ @@ -1487,6 +1583,8 @@ struct em_hw { #define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ #define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ #define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ +#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion + by EEPROM/Flash */ #define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ #define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */ #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ @@ -1544,6 +1642,10 @@ struct em_hw { #define E1000_STM_OPCODE 0xDB00 #define E1000_HICR_FW_RESET 0xC0 +#define E1000_SHADOW_RAM_WORDS 2048 +#define E1000_ICH8_NVM_SIG_WORD 0x13 +#define E1000_ICH8_NVM_SIG_MASK 0xC0 + /* EEPROM Read */ #define E1000_EERD_START 0x00000001 /* Start Read */ #define E1000_EERD_DONE 0x00000010 /* Read Done */ @@ -1589,7 +1691,6 @@ struct em_hw { #define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 #define E1000_CTRL_EXT_WR_WMARK_384 0x02000000 #define E1000_CTRL_EXT_WR_WMARK_448 0x03000000 -#define E1000_CTRL_EXT_CANC 0x04000000 /* Interrupt delay cancellation */ #define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ #define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ #define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ @@ -1629,12 +1730,31 @@ struct em_hw { #define E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS 0x00000800 /* In-Band Control */ +#define E1000_KUMCTRLSTA_INB_CTRL_LINK_STATUS_TX_TIMEOUT_DEFAULT 0x00000500 #define E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING 0x00000010 /* Half-Duplex Control */ #define E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004 #define E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT 0x00000000 +#define E1000_KUMCTRLSTA_OFFSET_K0S_CTRL 0x0000001E + +#define E1000_KUMCTRLSTA_DIAG_FELPBK 0x2000 +#define E1000_KUMCTRLSTA_DIAG_NELPBK 0x1000 + +#define E1000_KUMCTRLSTA_K0S_100_EN 0x2000 +#define E1000_KUMCTRLSTA_K0S_GBE_EN 0x1000 +#define E1000_KUMCTRLSTA_K0S_ENTRY_LATENCY_MASK 0x0003 + +#define E1000_KABGTXD_BGSQLBIAS 0x00050000 + +#define E1000_PHY_CTRL_SPD_EN 0x00000001 +#define E1000_PHY_CTRL_D0A_LPLU 0x00000002 +#define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004 +#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008 +#define E1000_PHY_CTRL_GBE_DISABLE 0x00000040 +#define E1000_PHY_CTRL_B2B_EN 0x00000080 + /* LED Control */ #define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F #define E1000_LEDCTL_LED0_MODE_SHIFT 0 @@ -1704,6 +1824,9 @@ struct em_hw { #define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */ #define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */ #define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */ +#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */ +#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */ +#define E1000_ICR_EPRST 0x00100000 /* ME handware reset occurs */ /* Interrupt Cause Set */ #define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1730,6 +1853,9 @@ struct em_hw { #define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ #define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ #define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ +#define E1000_ICS_DSW E1000_ICR_DSW +#define E1000_ICS_PHYINT E1000_ICR_PHYINT +#define E1000_ICS_EPRST E1000_ICR_EPRST /* Interrupt Mask Set */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1756,6 +1882,9 @@ struct em_hw { #define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ #define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ #define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ +#define E1000_IMS_DSW E1000_ICR_DSW +#define E1000_IMS_PHYINT E1000_ICR_PHYINT +#define E1000_IMS_EPRST E1000_ICR_EPRST /* Interrupt Mask Clear */ #define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1782,6 +1911,9 @@ struct em_hw { #define E1000_IMC_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ #define E1000_IMC_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ #define E1000_IMC_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ +#define E1000_IMC_DSW E1000_ICR_DSW +#define E1000_IMC_PHYINT E1000_ICR_PHYINT +#define E1000_IMC_EPRST E1000_ICR_EPRST /* Receive Control */ #define E1000_RCTL_RST 0x00000001 /* Software reset */ @@ -1840,7 +1972,7 @@ struct em_hw { * value2 = [0..64512], default=4096 * value3 = [0..64512], default=0 */ - + #define E1000_PSRCTL_BSIZE0_MASK 0x0000007F #define E1000_PSRCTL_BSIZE1_MASK 0x00003F00 #define E1000_PSRCTL_BSIZE2_MASK 0x003F0000 @@ -1956,9 +2088,10 @@ struct em_hw { #define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000 #define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 #define E1000_MRQC_RSS_FIELD_IPV4 0x00020000 -#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00040000 +#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 #define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000 #define E1000_MRQC_RSS_FIELD_IPV6 0x00100000 +#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 /* Definitions for power management and wakeup registers */ /* Wake Up Control */ @@ -2026,7 +2159,7 @@ struct em_hw { #define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000 /* Enable IP address * filtering */ #define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable checksum filtering */ -#define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */ +#define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */ #define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */ #define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */ #define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */ @@ -2048,6 +2181,15 @@ struct em_hw { #define E1000_FWSM_MODE_SHIFT 1 #define E1000_FWSM_FW_VALID 0x00008000 /* FW established a valid mode */ +#define E1000_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI reset */ +#define E1000_FWSM_DISSW 0x10000000 /* FW disable SW Write Access */ +#define E1000_FWSM_SKUSEL_MASK 0x60000000 /* LAN SKU select */ +#define E1000_FWSM_SKUEL_SHIFT 29 +#define E1000_FWSM_SKUSEL_EMB 0x0 /* Embedded SKU */ +#define E1000_FWSM_SKUSEL_CONS 0x1 /* Consumer SKU */ +#define E1000_FWSM_SKUSEL_PERF_100 0x2 /* Perf & Corp 10/100 SKU */ +#define E1000_FWSM_SKUSEL_PERF_GBE 0x3 /* Perf & Copr GbE SKU */ + /* FFLT Debug Register */ #define E1000_FFLT_DBG_INVC 0x00100000 /* Invalid /C/ code handling */ @@ -2120,6 +2262,8 @@ struct em_host_command_info { E1000_GCR_TXDSCW_NO_SNOOP | \ E1000_GCR_TXDSCR_NO_SNOOP) +#define PCI_EX_82566_SNOOP_ALL PCI_EX_NO_SNOOP_ALL + #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 /* Function Active and Power State to MNG */ #define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003 @@ -2153,7 +2297,7 @@ struct em_host_command_info { #define EEPROM_EWDS_OPCODE_MICROWIRE 0x10 /* EEPROM erast/write disable */ /* EEPROM Commands - SPI */ -#define EEPROM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ +#define EEPROM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ #define EEPROM_READ_OPCODE_SPI 0x03 /* EEPROM read opcode */ #define EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */ #define EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */ @@ -2178,8 +2322,10 @@ struct em_host_command_info { #define EEPROM_PHY_CLASS_WORD 0x0007 #define EEPROM_INIT_CONTROL1_REG 0x000A #define EEPROM_INIT_CONTROL2_REG 0x000F +#define EEPROM_SWDEF_PINS_CTRL_PORT_1 0x0010 #define EEPROM_INIT_CONTROL3_PORT_B 0x0014 #define EEPROM_INIT_3GIO_3 0x001A +#define EEPROM_SWDEF_PINS_CTRL_PORT_0 0x0020 #define EEPROM_INIT_CONTROL3_PORT_A 0x0024 #define EEPROM_CFG 0x0012 #define EEPROM_FLASH_VERSION 0x0032 @@ -2191,10 +2337,16 @@ struct em_host_command_info { /* Word definitions for ID LED Settings */ #define ID_LED_RESERVED_0000 0x0000 #define ID_LED_RESERVED_FFFF 0xFFFF +#define ID_LED_RESERVED_82573 0xF746 +#define ID_LED_DEFAULT_82573 0x1811 #define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ (ID_LED_OFF1_OFF2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_DEF1_DEF2)) +#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \ + (ID_LED_DEF1_OFF2 << 8) | \ + (ID_LED_DEF1_ON2 << 4) | \ + (ID_LED_DEF1_DEF2)) #define ID_LED_DEF1_DEF2 0x1 #define ID_LED_DEF1_ON2 0x2 #define ID_LED_DEF1_OFF2 0x3 @@ -2228,6 +2380,11 @@ struct em_host_command_info { #define EEPROM_WORD0F_ASM_DIR 0x2000 #define EEPROM_WORD0F_ANE 0x0800 #define EEPROM_WORD0F_SWPDIO_EXT 0x00F0 +#define EEPROM_WORD0F_LPLU 0x0001 + +/* Mask bits for fields in Word 0x10/0x20 of the EEPROM */ +#define EEPROM_WORD1020_GIGA_DISABLE 0x0010 +#define EEPROM_WORD1020_GIGA_DISABLE_NON_D0A 0x0008 /* Mask bits for fields in Word 0x1a of the EEPROM */ #define EEPROM_WORD1A_ASPM_MASK 0x000C @@ -2302,23 +2459,29 @@ struct em_host_command_info { #define E1000_EXTCNF_CTRL_D_UD_OWNER 0x00000010 #define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 #define E1000_EXTCNF_CTRL_MDIO_HW_OWNERSHIP 0x00000040 -#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER 0x1FFF0000 +#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER 0x0FFF0000 #define E1000_EXTCNF_SIZE_EXT_PHY_LENGTH 0x000000FF #define E1000_EXTCNF_SIZE_EXT_DOCK_LENGTH 0x0000FF00 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH 0x00FF0000 +#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 +#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 /* PBA constants */ +#define E1000_PBA_8K 0x0008 /* 8KB, default Rx allocation */ #define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */ #define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ #define E1000_PBA_22K 0x0016 #define E1000_PBA_24K 0x0018 #define E1000_PBA_30K 0x001E #define E1000_PBA_32K 0x0020 +#define E1000_PBA_34K 0x0022 #define E1000_PBA_38K 0x0026 #define E1000_PBA_40K 0x0028 #define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */ +#define E1000_PBS_16K E1000_PBA_16K + /* Flow Control Constants */ #define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 #define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 @@ -2371,7 +2534,7 @@ struct em_host_command_info { /* Number of milliseconds we wait for Eeprom auto read bit done after MAC reset */ #define AUTO_READ_DONE_TIMEOUT 10 /* Number of milliseconds we wait for PHY configuration done after MAC reset */ -#define PHY_CFG_TIMEOUT 40 +#define PHY_CFG_TIMEOUT 100 #define E1000_TX_BUFFER_SIZE ((uint32_t)1514) @@ -2798,6 +2961,17 @@ struct em_host_command_info { #define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ #define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ +/* M88EC018 Rev 2 specific DownShift settings */ +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_1X 0x0000 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_2X 0x0200 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_3X 0x0400 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_4X 0x0600 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_6X 0x0A00 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X 0x0C00 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X 0x0E00 + /* IGP01E1000 Specific Port Config Register - R/W */ #define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT 0x0010 #define IGP01E1000_PSCFR_PRE_EN 0x0020 @@ -2977,10 +3151,10 @@ struct em_host_command_info { /* DSP Distance Register (Page 5, Register 26) */ #define GG82563_DSPD_CABLE_LENGTH 0x0007 /* 0 = <50M; - 1 = 50-80M; - 2 = 80-110M; - 3 = 110-140M; - 4 = >140M */ + 1 = 50-80M; + 2 = 80-110M; + 3 = 110-140M; + 4 = >140M */ /* Kumeran Mode Control Register (Page 193, Register 16) */ #define GG82563_KMCR_PHY_LEDS_EN 0x0020 /* 1=PHY LEDs, 0=Kumeran Inband LEDs */ @@ -3023,6 +3197,193 @@ struct em_host_command_info { #define L1LXT971A_PHY_ID 0x001378E0 #define GG82563_E_PHY_ID 0x01410CA0 +/* Bits... + * 15-5: page + * 4-0: register offset + */ +#define PHY_PAGE_SHIFT 5 +#define PHY_REG(page, reg) \ + (((page) << PHY_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS)) + +#define IGP3_PHY_PORT_CTRL \ + PHY_REG(769, 17) /* Port General Configuration */ +#define IGP3_PHY_RATE_ADAPT_CTRL \ + PHY_REG(769, 25) /* Rate Adapter Control Register */ + +#define IGP3_KMRN_FIFO_CTRL_STATS \ + PHY_REG(770, 16) /* KMRN FIFO's control/status register */ +#define IGP3_KMRN_POWER_MNG_CTRL \ + PHY_REG(770, 17) /* KMRN Power Management Control Register */ +#define IGP3_KMRN_INBAND_CTRL \ + PHY_REG(770, 18) /* KMRN Inband Control Register */ +#define IGP3_KMRN_DIAG \ + PHY_REG(770, 19) /* KMRN Diagnostic register */ +#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 /* RX PCS is not synced */ +#define IGP3_KMRN_ACK_TIMEOUT \ + PHY_REG(770, 20) /* KMRN Acknowledge Timeouts register */ + +#define IGP3_VR_CTRL \ + PHY_REG(776, 18) /* Voltage regulator control register */ +#define IGP3_VR_CTRL_MODE_SHUT 0x0200 /* Enter powerdown, shutdown VRs */ + +#define IGP3_CAPABILITY \ + PHY_REG(776, 19) /* IGP3 Capability Register */ + +/* Capabilities for SKU Control */ +#define IGP3_CAP_INITIATE_TEAM 0x0001 /* Able to initiate a team */ +#define IGP3_CAP_WFM 0x0002 /* Support WoL and PXE */ +#define IGP3_CAP_ASF 0x0004 /* Support ASF */ +#define IGP3_CAP_LPLU 0x0008 /* Support Low Power Link Up */ +#define IGP3_CAP_DC_AUTO_SPEED 0x0010 /* Support AC/DC Auto Link Speed */ +#define IGP3_CAP_SPD 0x0020 /* Support Smart Power Down */ +#define IGP3_CAP_MULT_QUEUE 0x0040 /* Support 2 tx & 2 rx queues */ +#define IGP3_CAP_RSS 0x0080 /* Support RSS */ +#define IGP3_CAP_8021PQ 0x0100 /* Support 802.1Q & 802.1p */ +#define IGP3_CAP_AMT_CB 0x0200 /* Support active manageability and circuit breaker */ + +#define IGP3_PPC_JORDAN_EN 0x0001 +#define IGP3_PPC_JORDAN_GIGA_SPEED 0x0002 + +#define IGP3_KMRN_PMC_EE_IDLE_LINK_DIS 0x0001 +#define IGP3_KMRN_PMC_K0S_ENTRY_LATENCY_MASK 0x001E +#define IGP3_KMRN_PMC_K0S_MODE1_EN_GIGA 0x0020 +#define IGP3_KMRN_PMC_K0S_MODE1_EN_100 0x0040 + +#define IGP3E1000_PHY_MISC_CTRL 0x1B /* Misc. Ctrl register */ +#define IGP3_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Duplex Manual Set */ + +#define IGP3_KMRN_EXT_CTRL PHY_REG(770, 18) +#define IGP3_KMRN_EC_DIS_INBAND 0x0080 + +#define IGP03E1000_E_PHY_ID 0x02A80390 +#define IFE_E_PHY_ID 0x02A80330 /* 10/100 PHY */ +#define IFE_PLUS_E_PHY_ID 0x02A80320 +#define IFE_C_E_PHY_ID 0x02A80310 + +#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 /* 100BaseTx Extended Status, Control and Address */ +#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY special control register */ +#define IFE_PHY_RCV_FALSE_CARRIER 0x13 /* 100BaseTx Receive False Carrier Counter */ +#define IFE_PHY_RCV_DISCONNECT 0x14 /* 100BaseTx Receive Disconnet Counter */ +#define IFE_PHY_RCV_ERROT_FRAME 0x15 /* 100BaseTx Receive Error Frame Counter */ +#define IFE_PHY_RCV_SYMBOL_ERR 0x16 /* Receive Symbol Error Counter */ +#define IFE_PHY_PREM_EOF_ERR 0x17 /* 100BaseTx Receive Premature End Of Frame Error Counter */ +#define IFE_PHY_RCV_EOF_ERR 0x18 /* 10BaseT Receive End Of Frame Error Counter */ +#define IFE_PHY_TX_JABBER_DETECT 0x19 /* 10BaseT Transmit Jabber Detect Counter */ +#define IFE_PHY_EQUALIZER 0x1A /* PHY Equalizer Control and Status */ +#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY special control and LED configuration */ +#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control register */ +#define IFE_PHY_HWI_CONTROL 0x1D /* Hardware Integrity Control (HWI) */ + +#define IFE_PESC_REDUCED_POWER_DOWN_DISABLE 0x2000 /* Defaut 1 = Disable auto reduced power down */ +#define IFE_PESC_100BTX_POWER_DOWN 0x0400 /* Indicates the power state of 100BASE-TX */ +#define IFE_PESC_10BTX_POWER_DOWN 0x0200 /* Indicates the power state of 10BASE-T */ +#define IFE_PESC_POLARITY_REVERSED 0x0100 /* Indicates 10BASE-T polarity */ +#define IFE_PESC_PHY_ADDR_MASK 0x007C /* Bit 6:2 for sampled PHY address */ +#define IFE_PESC_SPEED 0x0002 /* Auto-negotiation speed result 1=100Mbs, 0=10Mbs */ +#define IFE_PESC_DUPLEX 0x0001 /* Auto-negotiation duplex result 1=Full, 0=Half */ +#define IFE_PESC_POLARITY_REVERSED_SHIFT 8 + +#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 /* 1 = Dyanmic Power Down disabled */ +#define IFE_PSC_FORCE_POLARITY 0x0020 /* 1=Reversed Polarity, 0=Normal */ +#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 /* 1=Auto Polarity Disabled, 0=Enabled */ +#define IFE_PSC_JABBER_FUNC_DISABLE 0x0001 /* 1=Jabber Disabled, 0=Normal Jabber Operation */ +#define IFE_PSC_FORCE_POLARITY_SHIFT 5 +#define IFE_PSC_AUTO_POLARITY_DISABLE_SHIFT 4 + +#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable MDI/MDI-X feature, default 0=disabled */ +#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDIX-X, 0=force MDI */ +#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ +#define IFE_PMC_AUTO_MDIX_COMPLETE 0x0010 /* Resolution algorthm is completed */ +#define IFE_PMC_MDIX_MODE_SHIFT 6 +#define IFE_PHC_MDIX_RESET_ALL_MASK 0x0000 /* Disable auto MDI-X */ + +#define IFE_PHC_HWI_ENABLE 0x8000 /* Enable the HWI feature */ +#define IFE_PHC_ABILITY_CHECK 0x4000 /* 1= Test Passed, 0=failed */ +#define IFE_PHC_TEST_EXEC 0x2000 /* PHY launch test pulses on the wire */ +#define IFE_PHC_HIGHZ 0x0200 /* 1 = Open Circuit */ +#define IFE_PHC_LOWZ 0x0400 /* 1 = Short Circuit */ +#define IFE_PHC_LOW_HIGH_Z_MASK 0x0600 /* Mask for indication type of problem on the line */ +#define IFE_PHC_DISTANCE_MASK 0x01FF /* Mask for distance to the cable problem, in 80cm granularity */ +#define IFE_PHC_RESET_ALL_MASK 0x0000 /* Disable HWI */ +#define IFE_PSCL_PROBE_MODE 0x0020 /* LED Probe mode */ +#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ +#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ + +#define ICH8_FLASH_COMMAND_TIMEOUT 500 /* 500 ms , should be adjusted */ +#define ICH8_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles , should be adjusted */ +#define ICH8_FLASH_SEG_SIZE_256 256 +#define ICH8_FLASH_SEG_SIZE_4K 4096 +#define ICH8_FLASH_SEG_SIZE_64K 65536 + +#define ICH8_CYCLE_READ 0x0 +#define ICH8_CYCLE_RESERVED 0x1 +#define ICH8_CYCLE_WRITE 0x2 +#define ICH8_CYCLE_ERASE 0x3 + +#define ICH8_FLASH_GFPREG 0x0000 +#define ICH8_FLASH_HSFSTS 0x0004 +#define ICH8_FLASH_HSFCTL 0x0006 +#define ICH8_FLASH_FADDR 0x0008 +#define ICH8_FLASH_FDATA0 0x0010 +#define ICH8_FLASH_FRACC 0x0050 +#define ICH8_FLASH_FREG0 0x0054 +#define ICH8_FLASH_FREG1 0x0058 +#define ICH8_FLASH_FREG2 0x005C +#define ICH8_FLASH_FREG3 0x0060 +#define ICH8_FLASH_FPR0 0x0074 +#define ICH8_FLASH_FPR1 0x0078 +#define ICH8_FLASH_SSFSTS 0x0090 +#define ICH8_FLASH_SSFCTL 0x0092 +#define ICH8_FLASH_PREOP 0x0094 +#define ICH8_FLASH_OPTYPE 0x0096 +#define ICH8_FLASH_OPMENU 0x0098 + +#define ICH8_FLASH_REG_MAPSIZE 0x00A0 +#define ICH8_FLASH_SECTOR_SIZE 4096 +#define ICH8_GFPREG_BASE_MASK 0x1FFF +#define ICH8_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF + +/* ICH8 GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ +/* Offset 04h HSFSTS */ +union ich8_hws_flash_status { + struct ich8_hsfsts { + uint16_t flcdone :1; /* bit 0 Flash Cycle Done */ + uint16_t flcerr :1; /* bit 1 Flash Cycle Error */ + uint16_t dael :1; /* bit 2 Direct Access error Log */ + uint16_t berasesz :2; /* bit 4:3 Block/Sector Erase Size */ + uint16_t flcinprog :1; /* bit 5 flash SPI cycle in Progress */ + uint16_t reserved1 :2; /* bit 13:6 Reserved */ + uint16_t reserved2 :6; /* bit 13:6 Reserved */ + uint16_t fldesvalid :1; /* bit 14 Flash Descriptor Valid */ + uint16_t flockdn :1; /* bit 15 Flash Configuration Lock-Down */ + } hsf_status; + uint16_t regval; +}; + +/* ICH8 GbE Flash Hardware Sequencing Flash control Register bit breakdown */ +/* Offset 06h FLCTL */ +union ich8_hws_flash_ctrl { + struct ich8_hsflctl { + uint16_t flcgo :1; /* 0 Flash Cycle Go */ + uint16_t flcycle :2; /* 2:1 Flash Cycle */ + uint16_t reserved :5; /* 7:3 Reserved */ + uint16_t fldbcount :2; /* 9:8 Flash Data Byte Count */ + uint16_t flockdn :6; /* 15:10 Reserved */ + } hsf_ctrl; + uint16_t regval; +}; + +/* ICH8 Flash Region Access Permissions */ +union ich8_hws_flash_regacc { + struct ich8_flracc { + uint32_t grra :8; /* 0:7 GbE region Read Access */ + uint32_t grwa :8; /* 8:15 GbE region Write Access */ + uint32_t gmrag :8; /* 23:16 GbE Master Read Access Grant */ + uint32_t gmwag :8; /* 31:24 GbE Master Write Access Grant */ + } hsf_flregacc; + uint16_t regval; +}; + /* Miscellaneous PHY bit definitions. */ #define PHY_PREAMBLE 0xFFFFFFFF #define PHY_SOF 0x01 diff --git a/sys/dev/pci/if_em_osdep.h b/sys/dev/pci/if_em_osdep.h index f8296474b72..70968a04677 100644 --- a/sys/dev/pci/if_em_osdep.h +++ b/sys/dev/pci/if_em_osdep.h @@ -1,6 +1,6 @@ /************************************************************************** -Copyright (c) 2001-2003, Intel Corporation +Copyright (c) 2001-2006, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ -/* $OpenBSD: if_em_osdep.h,v 1.8 2006/07/05 01:15:30 brad Exp $ */ +/* $OpenBSD: if_em_osdep.h,v 1.9 2006/07/07 02:56:18 brad Exp $ */ /* $FreeBSD: if_em_osdep.h,v 1.11 2003/05/02 21:17:08 pdeuskar Exp $ */ #ifndef _EM_OPENBSD_OS_H_ @@ -65,74 +65,106 @@ struct em_osdep { bus_space_tag_t mem_bus_space_tag; bus_space_handle_t mem_bus_space_handle; + bus_space_tag_t io_bus_space_tag; + bus_space_handle_t io_bus_space_handle; + bus_space_tag_t flash_bus_space_tag; + bus_space_handle_t flash_bus_space_handle; struct device *dev; struct pci_attach_args em_pa; bus_size_t em_memsize; bus_addr_t em_membase; - - bus_space_handle_t em_iobhandle; - bus_space_tag_t em_iobtag; bus_size_t em_iosize; bus_addr_t em_iobase; + bus_size_t em_flashsize; + bus_addr_t em_flashbase; }; #define E1000_WRITE_FLUSH(hw) E1000_READ_REG(hw, STATUS) /* Read from an absolute offset in the adapter's memory space */ #define E1000_READ_OFFSET(hw, offset) \ - bus_space_read_4( ((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ - ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ - offset) + bus_space_read_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ + offset) /* Write to an absolute offset in the adapter's memory space */ #define E1000_WRITE_OFFSET(hw, offset, value) \ - bus_space_write_4( ((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ - ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ - offset, value) + bus_space_write_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ + offset, value) /* Convert a register name to its offset in the adapter's memory space */ #define E1000_REG_OFFSET(hw, reg) \ ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg) +/* Register READ/WRITE macros */ + #define E1000_READ_REG(hw, reg) \ - E1000_READ_OFFSET(hw, E1000_REG_OFFSET(hw, reg)) + bus_space_read_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ + ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg)) #define E1000_WRITE_REG(hw, reg, value) \ - E1000_WRITE_OFFSET(hw, E1000_REG_OFFSET(hw, reg), value) + bus_space_write_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ + ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg), \ + value) #define E1000_READ_REG_ARRAY(hw, reg, index) \ - E1000_READ_OFFSET(hw, E1000_REG_OFFSET(hw, reg) + ((index) << 2)) - -#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY + bus_space_read_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ + ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg) \ + + ((index) << 2)) #define E1000_WRITE_REG_ARRAY(hw, reg, index, value) \ - E1000_WRITE_OFFSET(hw, E1000_REG_OFFSET(hw, reg) + ((index) << 2), value) + bus_space_write_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ + ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg) \ + + ((index) << 2), value) + +#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY +#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY #define E1000_WRITE_REG_ARRAY_BYTE(hw, reg, index, value) \ - bus_space_write_1( ((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ - ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ - E1000_REG_OFFSET(hw, reg) + (index), \ - value) + bus_space_write_1(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ + ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg \ + + index), value) #define E1000_WRITE_REG_ARRAY_WORD(hw, reg, index, value) \ - bus_space_write_2( ((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ - ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ - E1000_REG_OFFSET(hw, reg) + (index), \ - value) + bus_space_write_2(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ + ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg \ + + (index << 1)), value) + +#define E1000_READ_ICH8_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) + +#define E1000_READ_ICH8_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) + +#define E1000_WRITE_ICH8_REG(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, \ + reg, value) -#define E1000_WRITE_REG_ARRAY_DWORD(hw, reg, index, value) \ - E1000_WRITE_OFFSET(hw, E1000_REG_OFFSET(hw, reg) + ((index) << 2), value) +#define E1000_WRITE_ICH8_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) #define em_io_read(hw, port) \ - bus_space_read_4(((struct em_osdep *)(hw)->back)->em_iobtag, \ - ((struct em_osdep *)(hw)->back)->em_iobhandle, (port)) + bus_space_read_4(((struct em_osdep *)(hw)->back)->io_bus_space_tag, \ + ((struct em_osdep *)(hw)->back)->io_bus_space_handle, (port)) #define em_io_write(hw, port, value) \ - bus_space_write_4(((struct em_osdep *)(hw)->back)->em_iobtag, \ - ((struct em_osdep *)(hw)->back)->em_iobhandle, \ - (port), (value)) + bus_space_write_4(((struct em_osdep *)(hw)->back)->io_bus_space_tag, \ + ((struct em_osdep *)(hw)->back)->io_bus_space_handle, \ + (port), (value)) #ifdef DEBUG #define EM_KASSERT(exp,msg) do { if (!(exp)) panic msg; } while (0) |