diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2006-03-28 05:33:04 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2006-03-28 05:33:04 +0000 |
commit | 42a222d063e9f2a25f4df603095f6c6680ea59fc (patch) | |
tree | 2f32b096f1b208f6be1904bff9c62008dfb84341 /sys/dev/pci | |
parent | dfbe3f4f54568b5eedfe5695987a22e774114f2a (diff) |
Sync up to Intel's latest FreeBSD em driver (5.1.5). Adds support
for the 82563 PCI Express chipset and a few fixes.
From: Intel's web-site
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_em.c | 86 | ||||
-rw-r--r-- | sys/dev/pci/if_em_hw.c | 857 | ||||
-rw-r--r-- | sys/dev/pci/if_em_hw.h | 335 |
3 files changed, 1195 insertions, 83 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c index 69c7f09163d..6b2896a77b5 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.111 2006/03/27 18:01:53 brad Exp $ */ +/* $OpenBSD: if_em.c,v 1.112 2006/03/28 05:33:03 brad Exp $ */ /* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */ #include <dev/pci/if_em.h> @@ -45,12 +45,14 @@ int em_display_debug_stats = 0; * Driver version *********************************************************************/ -char em_driver_version[] = "3.2.18"; +char em_driver_version[] = "5.1.5"; /********************************************************************* * PCI Device ID Table *********************************************************************/ 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_82540EM }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EM_LOM }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EP }, @@ -242,7 +244,8 @@ em_attach(struct device *parent, struct device *self, void *aux) switch (sc->hw.mac_type) { case em_82571: case em_82572: - sc->hw.max_frame_size = 10500; + case em_80003es2lan: /* Limit Jumbo Frame size */ + sc->hw.max_frame_size = 9234; break; case em_82573: /* 82573 does not support Jumbo frames */ @@ -332,6 +335,11 @@ em_attach(struct device *parent, struct device *self, void *aux) printf(", address %s\n", ether_sprintf(sc->interface_data.ac_enaddr)); + /* Indicate SOL/IDER usage */ + if (em_check_phy_reset_block(&sc->hw)) + printf("%s: PHY reset is blocked due to SOL/IDER session.\n", + sc->sc_dv.dv_xname); + /* Identify 82544 on PCI-X */ em_get_bus_info(&sc->hw); if (sc->hw.bus_type == em_bus_type_pcix && @@ -440,6 +448,7 @@ int em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) { int max_frame_size, error = 0; + uint16_t eeprom_data = 0; struct ifreq *ifr = (struct ifreq *) data; struct ifaddr *ifa = (struct ifaddr *)data; struct em_softc *sc = ifp->if_softc; @@ -471,13 +480,22 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) case SIOCSIFMTU: IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)"); switch (sc->hw.mac_type) { + case em_82573: + /* + * 82573 only supports Jumbo frames + * if ASPM is disabled. + */ + em_read_eeprom(&sc->hw, EEPROM_INIT_3GIO_3, + 1, &eeprom_data); + if (eeprom_data & EEPROM_WORD1A_ASPM_MASK) { + max_frame_size = ETHER_MAX_LEN; + break; + } + /* Allow Jumbo frames - FALLTHROUGH */ case em_82571: case em_82572: - max_frame_size = 10500; - break; - case em_82573: - /* 82573 does not support Jumbo frames */ - max_frame_size = ETHER_MAX_LEN; + case em_80003es2lan: /* Limit Jumbo Frame size */ + max_frame_size = 9234; break; default: max_frame_size = MAX_JUMBO_FRAME_SIZE; @@ -613,6 +631,7 @@ em_init(void *arg) sc->tx_head_addr = pba << EM_TX_HEAD_ADDR_SHIFT; sc->tx_fifo_size = (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT; break; + case em_80003es2lan: /* 80003es2lan: Total Packet Buffer is 48K */ case em_82571: /* 82571: Total Packet Buffer is 48K */ case em_82572: /* 82572: Total Packet Buffer is 48K */ pba = E1000_PBA_32K; /* 32K for Rx, 16K for Tx */ @@ -693,7 +712,7 @@ em_intr(void *arg) { struct em_softc *sc = arg; struct ifnet *ifp; - u_int32_t reg_icr; + u_int32_t reg_icr, test_icr; int s, claimed = 0; s = splnet(); @@ -701,12 +720,11 @@ em_intr(void *arg) ifp = &sc->interface_data.ac_if; for (;;) { - reg_icr = E1000_READ_REG(&sc->hw, ICR); - if (sc->hw.mac_type >= em_82571 && - (reg_icr & E1000_ICR_INT_ASSERTED) == 0) - break; - else if (reg_icr == 0) - break; + test_icr = reg_icr = E1000_READ_REG(&sc->hw, ICR); + if (sc->hw.mac_type >= em_82571) + test_icr = (reg_icr & E1000_ICR_INT_ASSERTED); + if (!test_icr) + return (0); claimed = 1; @@ -1468,7 +1486,10 @@ em_hardware_init(struct em_softc *sc) sc->hw.fc_high_water = rx_buffer_size - EM_ROUNDUP(sc->hw.max_frame_size, 1024); sc->hw.fc_low_water = sc->hw.fc_high_water - 1500; - sc->hw.fc_pause_time = 0x1000; + if (sc->hw.mac_type == em_80003es2lan) + sc->hw.fc_pause_time = 0xFFFF; + else + sc->hw.fc_pause_time = 0x1000; sc->hw.fc_send_xon = TRUE; sc->hw.fc = em_fc_full; @@ -1729,7 +1750,7 @@ em_setup_transmit_structures(struct em_softc *sc) void em_initialize_transmit_unit(struct em_softc *sc) { - u_int32_t reg_tctl; + u_int32_t reg_tctl, tarc; u_int32_t reg_tipg = 0; u_int64_t bus_addr; @@ -1758,6 +1779,10 @@ em_initialize_transmit_unit(struct em_softc *sc) reg_tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; reg_tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; break; + case em_80003es2lan: + reg_tipg = DEFAULT_82543_TIPG_IPGR1; + reg_tipg |= DEFAULT_80003ES2LAN_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; + break; default: if (sc->hw.media_type == em_media_type_fiber) reg_tipg = DEFAULT_82543_TIPG_IPGT_FIBER; @@ -1777,13 +1802,34 @@ em_initialize_transmit_unit(struct em_softc *sc) (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); if (sc->hw.mac_type >= em_82571) reg_tctl |= E1000_TCTL_MULR; - if (sc->link_duplex == 1) { + if (sc->link_duplex == 1) reg_tctl |= E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT; - } else { + else reg_tctl |= E1000_HDX_COLLISION_DISTANCE << E1000_COLD_SHIFT; - } 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; diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c index 6cef49b5476..b9044d3b46c 100644 --- a/sys/dev/pci/if_em_hw.c +++ b/sys/dev/pci/if_em_hw.c @@ -31,7 +31,8 @@ POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ -/* $OpenBSD: if_em_hw.c,v 1.15 2006/03/07 09:21:55 jmc Exp $ */ +/* $OpenBSD: if_em_hw.c,v 1.16 2006/03/28 05:33:03 brad Exp $ */ + /* if_em_hw.c * Shared functions for accessing and configuring the MAC */ @@ -106,6 +107,8 @@ 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); /* IGP cable length table */ static const @@ -158,6 +161,11 @@ em_set_phy_type(struct em_hw *hw) hw->phy_type = em_phy_igp; break; } + case GG82563_E_PHY_ID: + if (hw->mac_type == em_80003es2lan) { + hw->phy_type = em_phy_gg82563; + break; + } /* FALLTHROUGH */ default: /* Should never have loaded on this device */ @@ -324,6 +332,7 @@ em_set_mac_type(struct em_hw *hw) case E1000_DEV_ID_82546GB_SERDES: case E1000_DEV_ID_82546GB_PCIE: case E1000_DEV_ID_82546GB_QUAD_COPPER: + case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: hw->mac_type = em_82546_rev_3; break; case E1000_DEV_ID_82541EI: @@ -352,6 +361,7 @@ em_set_mac_type(struct em_hw *hw) case E1000_DEV_ID_82572EI_COPPER: case E1000_DEV_ID_82572EI_FIBER: case E1000_DEV_ID_82572EI_SERDES: + case E1000_DEV_ID_82572EI: hw->mac_type = em_82572; break; case E1000_DEV_ID_82573E: @@ -359,12 +369,19 @@ em_set_mac_type(struct em_hw *hw) case E1000_DEV_ID_82573L: hw->mac_type = em_82573; break; + case E1000_DEV_ID_80003ES2LAN_COPPER_DPT: + case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: + hw->mac_type = em_80003es2lan; + break; default: /* Should never have loaded on this device */ return -E1000_ERR_MAC_TYPE; } switch(hw->mac_type) { + case em_80003es2lan: + hw->swfw_sync_present = TRUE; + /* FALLTHROUGH */ case em_82571: case em_82572: case em_82573: @@ -405,6 +422,7 @@ em_set_media_type(struct em_hw *hw) case E1000_DEV_ID_82546GB_SERDES: case E1000_DEV_ID_82571EB_SERDES: case E1000_DEV_ID_82572EI_SERDES: + case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: hw->media_type = em_media_type_internal_serdes; break; default: @@ -581,6 +599,7 @@ em_reset_hw(struct em_hw *hw) /* FALLTHROUGH */ case em_82571: case em_82572: + case em_80003es2lan: ret_val = em_get_auto_rd_done(hw); if(ret_val) /* We don't want to continue accessing MAC registers. */ @@ -647,6 +666,8 @@ em_init_hw(struct em_hw *hw) uint16_t cmd_mmrbc; uint16_t stat_mmrbc; uint32_t mta_size; + uint32_t reg_data; + uint32_t ctrl_ext; DEBUGFUNC("em_init_hw"); @@ -743,8 +764,8 @@ em_init_hw(struct em_hw *hw) break; case em_82571: case em_82572: - ctrl |= (1 << 22); case em_82573: + case em_80003es2lan: ctrl |= E1000_TXDCTL_COUNT_DESC; break; } @@ -758,12 +779,34 @@ em_init_hw(struct em_hw *hw) switch (hw->mac_type) { default: break; + case em_80003es2lan: + /* Enable retransmit on late collisions */ + reg_data = E1000_READ_REG(hw, TCTL); + reg_data |= E1000_TCTL_RTLC; + E1000_WRITE_REG(hw, TCTL, reg_data); + + /* Configure Gigabit Carry Extend Padding */ + reg_data = E1000_READ_REG(hw, TCTL_EXT); + reg_data &= ~E1000_TCTL_EXT_GCEX_MASK; + reg_data |= DEFAULT_80003ES2LAN_TCTL_EXT_GCEX; + E1000_WRITE_REG(hw, TCTL_EXT, reg_data); + + /* Configure Transmit Inter-Packet Gap */ + reg_data = E1000_READ_REG(hw, TIPG); + reg_data &= ~E1000_TIPG_IPGT_MASK; + reg_data |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000; + E1000_WRITE_REG(hw, TIPG, reg_data); + + reg_data = E1000_READ_REG_ARRAY(hw, FFLT, 0x0001); + reg_data &= ~0x00100000; + E1000_WRITE_REG_ARRAY(hw, FFLT, 0x0001, reg_data); + /* FALLTHROUGH */ case em_82571: case em_82572: ctrl = E1000_READ_REG(hw, TXDCTL1); - ctrl &= ~E1000_TXDCTL_WTHRESH; - ctrl |= E1000_TXDCTL_COUNT_DESC | E1000_TXDCTL_FULL_TX_DESC_WB; - ctrl |= (1 << 22); + ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; + if(hw->mac_type >= em_82571) + ctrl |= E1000_TXDCTL_COUNT_DESC; E1000_WRITE_REG(hw, TXDCTL1, ctrl); break; } @@ -781,6 +824,15 @@ em_init_hw(struct em_hw *hw) */ em_clear_hw_cntrs(hw); + 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); + /* Relaxed ordering must be disabled to avoid a parity + * error crash in a PCI slot. */ + ctrl_ext |= E1000_CTRL_EXT_RO_DIS; + E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + } + return ret_val; } @@ -1292,7 +1344,7 @@ em_copper_link_igp_setup(struct em_hw *hw) break; case em_ms_auto: phy_data &= ~CR_1000T_MS_ENABLE; - break; + break; default: break; } @@ -1304,6 +1356,154 @@ em_copper_link_igp_setup(struct em_hw *hw) return E1000_SUCCESS; } +/******************************************************************** +* Copper link setup for em_phy_gg82563 series. +* +* hw - Struct containing variables accessed by shared code +*********************************************************************/ +static int32_t +em_copper_link_ggp_setup(struct em_hw *hw) +{ + int32_t ret_val; + uint16_t phy_data; + uint32_t reg_data; + + DEBUGFUNC("em_copper_link_ggp_setup"); + + 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) + return ret_val; + + phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; + /* Use 25MHz for both link down and 1000BASE-T for Tx clock */ + phy_data |= GG82563_MSCR_TX_CLK_1000MBPS_25MHZ; + + ret_val = em_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, + phy_data); + if(ret_val) + return ret_val; + + /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode + * 2 - MDI-X mode + * 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) + return ret_val; + + phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK; + + switch (hw->mdix) { + case 1: + phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDI; + break; + case 2: + phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDIX; + break; + case 0: + default: + phy_data |= GG82563_PSCR_CROSSOVER_MODE_AUTO; + break; + } + + /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled + */ + phy_data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE; + 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) + return ret_val; + + /* SW Reset the PHY so all changes take effect */ + ret_val = em_phy_reset(hw); + if (ret_val) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } + } /* phy_reset_disable */ + + if (hw->mac_type == em_80003es2lan) { + /* Bypass RX and TX FIFO's */ + ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL, + E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS | + E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS); + if (ret_val) + return ret_val; + + ret_val = em_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, &phy_data); + if (ret_val) + return ret_val; + + phy_data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG; + ret_val = em_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, phy_data); + + if (ret_val) + return ret_val; + + reg_data = E1000_READ_REG(hw, CTRL_EXT); + reg_data &= ~(E1000_CTRL_EXT_LINK_MODE_MASK); + E1000_WRITE_REG(hw, CTRL_EXT, reg_data); + + ret_val = em_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, + &phy_data); + if (ret_val) + return ret_val; + + /* Do not init these registers when the HW is in IAMT mode, since the + * firmware will have already initialized them. We only initialize + * them if the HW is not in IAMT mode. + */ + if (em_check_mng_mode(hw) == FALSE) { + /* Enable Electrical Idle on the PHY */ + phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; + ret_val = em_write_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, + phy_data); + if (ret_val) + return ret_val; + + ret_val = em_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + &phy_data); + 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; + } + + /* Workaround: Disable padding in Kumeran interface in the MAC + * and in the PHY to avoid CRC errors. + */ + ret_val = em_read_phy_reg(hw, GG82563_PHY_INBAND_CTRL, + &phy_data); + if (ret_val) + return ret_val; + phy_data |= GG82563_ICR_DIS_PADDING; + ret_val = em_write_phy_reg(hw, GG82563_PHY_INBAND_CTRL, + phy_data); + if (ret_val) + return ret_val; + } + + return E1000_SUCCESS; +} /******************************************************************** * Copper link setup for em_phy_m88 series. @@ -1514,14 +1714,50 @@ em_setup_copper_link(struct em_hw *hw) int32_t ret_val; uint16_t i; uint16_t phy_data; + uint16_t reg_data; DEBUGFUNC("em_setup_copper_link"); + switch (hw->mac_type) { + case em_80003es2lan: + /* 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. */ + ret_val = em_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF); + if (ret_val) + return ret_val; + ret_val = em_read_kmrn_reg(hw, GG82563_REG(0x34, 9), ®_data); + if (ret_val) + return ret_val; + reg_data |= 0x3F; + ret_val = em_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data); + if (ret_val) + return ret_val; + default: + break; + } + /* Check if it is a valid PHY and set PHY mode if necessary. */ ret_val = em_copper_link_preconfig(hw); 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; + reg_data |= E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING; + ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL, + reg_data); + if (ret_val) + return ret_val; + break; + default: + break; + } + if (hw->phy_type == em_phy_igp || hw->phy_type == em_phy_igp_2) { ret_val = em_copper_link_igp_setup(hw); @@ -1531,6 +1767,10 @@ em_setup_copper_link(struct em_hw *hw) ret_val = em_copper_link_mgp_setup(hw); 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) + return ret_val; } if(hw->autoneg) { @@ -1578,6 +1818,86 @@ em_setup_copper_link(struct em_hw *hw) } /****************************************************************************** +* Configure the MAC-to-PHY interface for 10/100Mbps +* +* hw - Struct containing variables accessed by shared code +******************************************************************************/ +static int32_t +em_configure_kmrn_for_10_100(struct em_hw *hw, uint16_t duplex) +{ + int32_t ret_val = E1000_SUCCESS; + uint32_t tipg; + uint16_t reg_data; + + DEBUGFUNC("em_configure_kmrn_for_10_100"); + + reg_data = E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT; + ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL, + reg_data); + if (ret_val) + return ret_val; + + /* Configure Transmit Inter-Packet Gap */ + tipg = E1000_READ_REG(hw, TIPG); + tipg &= ~E1000_TIPG_IPGT_MASK; + 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); + 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); + + return ret_val; +} + +static int32_t +em_configure_kmrn_for_1000(struct em_hw *hw, uint16_t duplex) +{ + int32_t ret_val = E1000_SUCCESS; + uint16_t reg_data; + uint32_t tipg; + + DEBUGFUNC("em_configure_kmrn_for_1000"); + + reg_data = E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT; + ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL, + reg_data); + if (ret_val) + return ret_val; + + /* Configure Transmit Inter-Packet Gap */ + tipg = E1000_READ_REG(hw, TIPG); + tipg &= ~E1000_TIPG_IPGT_MASK; + 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); + 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); + + return ret_val; +} + +/****************************************************************************** * Configures PHY autoneg and flow control advertisement settings * * hw - Struct containing variables accessed by shared code @@ -1596,10 +1916,10 @@ em_phy_setup_autoneg(struct em_hw *hw) 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; + /* 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; /* Need to parse both autoneg_advertised and fc and set up * the appropriate PHY registers. First we will parse for @@ -1798,7 +2118,8 @@ em_phy_force_speed_duplex(struct em_hw *hw) /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); - if (hw->phy_type == em_phy_m88) { + 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) return ret_val; @@ -1867,7 +2188,8 @@ em_phy_force_speed_duplex(struct em_hw *hw) msec_delay(100); } if((i == 0) && - (hw->phy_type == em_phy_m88)) { + ((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) { @@ -1926,6 +2248,27 @@ em_phy_force_speed_duplex(struct em_hw *hw) if(ret_val) return ret_val; } + } else if (hw->phy_type == em_phy_gg82563) { + /* The TX_CLK of the Extended PHY Specific Control Register defaults + * to 2.5MHz on a reset. We need to re-force it back to 25MHz, if + * we're not in a forced 10/duplex configuration. */ + ret_val = em_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); + if (ret_val) + return ret_val; + + phy_data &= ~GG82563_MSCR_TX_CLK_MASK; + if ((hw->forced_speed_duplex == em_10_full) || + (hw->forced_speed_duplex == em_10_half)) + phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ; + else + phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25MHZ; + + /* Also due to the reset, we need to enable CRS on Tx. */ + phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; + + ret_val = em_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data); + if (ret_val) + return ret_val; } return E1000_SUCCESS; } @@ -1941,14 +2284,19 @@ em_phy_force_speed_duplex(struct em_hw *hw) void em_config_collision_dist(struct em_hw *hw) { - uint32_t tctl; + uint32_t tctl, coll_dist; DEBUGFUNC("em_config_collision_dist"); + if (hw->mac_type < em_82543) + coll_dist = E1000_COLLISION_DISTANCE_82542; + else + coll_dist = E1000_COLLISION_DISTANCE; + tctl = E1000_READ_REG(hw, TCTL); tctl &= ~E1000_TCTL_COLD; - tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; + tctl |= coll_dist << E1000_COLD_SHIFT; E1000_WRITE_REG(hw, TCTL, tctl); E1000_WRITE_FLUSH(hw); @@ -2192,10 +2540,10 @@ em_config_fc_after_link_up(struct em_hw *hw) */ if(hw->original_fc == em_fc_full) { hw->fc = em_fc_full; - DEBUGOUT("Flow Control = FULL.\r\n"); + DEBUGOUT("Flow Control = FULL.\n"); } else { hw->fc = em_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } } /* For receiving PAUSE frames ONLY. @@ -2211,7 +2559,7 @@ em_config_fc_after_link_up(struct em_hw *hw) (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.\r\n"); + DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); } /* For transmitting PAUSE frames ONLY. * @@ -2226,7 +2574,7 @@ em_config_fc_after_link_up(struct em_hw *hw) !(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.\r\n"); + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } /* Per the IEEE spec, at this point flow control should be * disabled. However, we want to consider that we could @@ -2252,10 +2600,10 @@ em_config_fc_after_link_up(struct em_hw *hw) hw->original_fc == em_fc_tx_pause) || hw->fc_strict_ieee) { hw->fc = em_fc_none; - DEBUGOUT("Flow Control = NONE.\r\n"); + DEBUGOUT("Flow Control = NONE.\n"); } else { hw->fc = em_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } /* Now we need to do one last check... If we auto- @@ -2280,7 +2628,7 @@ em_config_fc_after_link_up(struct em_hw *hw) return ret_val; } } else { - DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n"); + DEBUGOUT("Copper PHY and Auto Neg has not completed.\n"); } } return E1000_SUCCESS; @@ -2463,7 +2811,7 @@ em_check_for_link(struct em_hw *hw) hw->autoneg_failed = 1; return 0; } - DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n"); + DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); /* Disable auto-negotiation in the TXCW register */ E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE)); @@ -2488,7 +2836,7 @@ em_check_for_link(struct em_hw *hw) 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.\r\n"); + 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)); @@ -2551,13 +2899,13 @@ em_get_speed_and_duplex(struct em_hw *hw, if(status & E1000_STATUS_FD) { *duplex = FULL_DUPLEX; - DEBUGOUT("Full Duplex\r\n"); + DEBUGOUT("Full Duplex\n"); } else { *duplex = HALF_DUPLEX; - DEBUGOUT(" Half Duplex\r\n"); + DEBUGOUT(" Half Duplex\n"); } } else { - DEBUGOUT("1000 Mbs, Full Duplex\r\n"); + DEBUGOUT("1000 Mbs, Full Duplex\n"); *speed = SPEED_1000; *duplex = FULL_DUPLEX; } @@ -2583,6 +2931,16 @@ em_get_speed_and_duplex(struct em_hw *hw, } } + 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); + else + ret_val = em_configure_kmrn_for_10_100(hw, *duplex); + if (ret_val) + return ret_val; + } + return E1000_SUCCESS; } @@ -2758,6 +3116,72 @@ em_shift_in_mdi_bits(struct em_hw *hw) return data; } +int32_t +em_swfw_sync_acquire(struct em_hw *hw, uint16_t mask) +{ + uint32_t swfw_sync = 0; + uint32_t swmask = mask; + uint32_t fwmask = mask << 16; + int32_t timeout = 200; + + DEBUGFUNC("em_swfw_sync_acquire"); + + if (!hw->swfw_sync_present) + return em_get_hw_eeprom_semaphore(hw); + + while(timeout) { + if (em_get_hw_eeprom_semaphore(hw)) + return -E1000_ERR_SWFW_SYNC; + + swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC); + if (!(swfw_sync & (fwmask | swmask))) { + break; + } + + /* firmware currently using resource (fwmask) */ + /* or other software thread currently using resource (swmask) */ + em_put_hw_eeprom_semaphore(hw); + msec_delay_irq(5); + timeout--; + } + + if (!timeout) { + DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); + return -E1000_ERR_SWFW_SYNC; + } + + swfw_sync |= swmask; + E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync); + + em_put_hw_eeprom_semaphore(hw); + return E1000_SUCCESS; +} + +void +em_swfw_sync_release(struct em_hw *hw, uint16_t mask) +{ + uint32_t swfw_sync; + uint32_t swmask = mask; + + DEBUGFUNC("em_swfw_sync_release"); + + if (!hw->swfw_sync_present) { + em_put_hw_eeprom_semaphore(hw); + return; + } + + /* if (em_get_hw_eeprom_semaphore(hw)) + * return -E1000_ERR_SWFW_SYNC; */ + while (em_get_hw_eeprom_semaphore(hw) != E1000_SUCCESS); + /* empty */ + + swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC); + swfw_sync &= ~swmask; + E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync); + + em_put_hw_eeprom_semaphore(hw); +} + /***************************************************************************** * Reads the value from a PHY register, if the value is on a specific non zero * page, sets the page first. @@ -2770,22 +3194,55 @@ em_read_phy_reg(struct em_hw *hw, uint16_t *phy_data) { uint32_t ret_val; + uint16_t swfw; DEBUGFUNC("em_read_phy_reg"); + if ((hw->mac_type == em_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (em_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + if((hw->phy_type == em_phy_igp || 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) { + em_swfw_sync_release(hw, swfw); return ret_val; } + } else if (hw->phy_type == em_phy_gg82563) { + if (((reg_addr & MAX_PHY_REG_ADDRESS) > MAX_PHY_MULTI_PAGE_REG) || + (hw->mac_type == em_80003es2lan)) { + /* Select Configuration Page */ + if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { + ret_val = em_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT, + (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT)); + } else { + /* Use Alternative Page Select register to access + * registers 30 and 31 + */ + ret_val = em_write_phy_reg_ex(hw, + GG82563_PHY_PAGE_SELECT_ALT, + (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT)); + } + + if (ret_val) { + em_swfw_sync_release(hw, swfw); + return ret_val; + } + } } ret_val = em_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, phy_data); + em_swfw_sync_release(hw, swfw); return ret_val; } @@ -2876,22 +3333,55 @@ em_write_phy_reg(struct em_hw *hw, uint16_t phy_data) { uint32_t ret_val; + uint16_t swfw; DEBUGFUNC("em_write_phy_reg"); + if ((hw->mac_type == em_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (em_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + if((hw->phy_type == em_phy_igp || 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) { + em_swfw_sync_release(hw, swfw); return ret_val; } + } else if (hw->phy_type == em_phy_gg82563) { + if (((reg_addr & MAX_PHY_REG_ADDRESS) > MAX_PHY_MULTI_PAGE_REG) || + (hw->mac_type == em_80003es2lan)) { + /* Select Configuration Page */ + if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { + ret_val = em_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT, + (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT)); + } else { + /* Use Alternative Page Select register to access + * registers 30 and 31 + */ + ret_val = em_write_phy_reg_ex(hw, + GG82563_PHY_PAGE_SELECT_ALT, + (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT)); + } + + if (ret_val) { + em_swfw_sync_release(hw, swfw); + return ret_val; + } + } } ret_val = em_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, phy_data); + em_swfw_sync_release(hw, swfw); return ret_val; } @@ -2924,7 +3414,7 @@ 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 < 640; i++) { + for(i = 0; i < 641; i++) { usec_delay(5); mdic = E1000_READ_REG(hw, MDIC); if(mdic & E1000_MDIC_READY) break; @@ -2958,6 +3448,65 @@ em_write_phy_reg_ex(struct em_hw *hw, return E1000_SUCCESS; } +int32_t +em_read_kmrn_reg(struct em_hw *hw, + uint32_t reg_addr, + uint16_t *data) +{ + uint32_t reg_val; + uint16_t swfw; + DEBUGFUNC("em_read_kmrn_reg"); + + if ((hw->mac_type == em_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (em_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + + /* Write register address */ + reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) & + E1000_KUMCTRLSTA_OFFSET) | + E1000_KUMCTRLSTA_REN; + E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val); + usec_delay(2); + + /* Read the data returned */ + reg_val = E1000_READ_REG(hw, KUMCTRLSTA); + *data = (uint16_t)reg_val; + + em_swfw_sync_release(hw, swfw); + return E1000_SUCCESS; +} + +int32_t +em_write_kmrn_reg(struct em_hw *hw, + uint32_t reg_addr, + uint16_t data) +{ + uint32_t reg_val; + uint16_t swfw; + DEBUGFUNC("em_write_kmrn_reg"); + + if ((hw->mac_type == em_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (em_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + + reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) & + E1000_KUMCTRLSTA_OFFSET) | data; + E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val); + usec_delay(2); + + em_swfw_sync_release(hw, swfw); + return E1000_SUCCESS; +} /****************************************************************************** * Returns the PHY to the power-on reset state @@ -2970,6 +3519,7 @@ em_phy_hw_reset(struct em_hw *hw) uint32_t ctrl, ctrl_ext; uint32_t led_ctrl; int32_t ret_val; + uint16_t swfw; DEBUGFUNC("em_phy_hw_reset"); @@ -2982,11 +3532,21 @@ em_phy_hw_reset(struct em_hw *hw) DEBUGOUT("Resetting Phy...\n"); 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; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (em_swfw_sync_acquire(hw, swfw)) { + em_release_software_semaphore(hw); + return -E1000_ERR_SWFW_SYNC; + } /* 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 * and deassert. For em_82571 hardware and later, we instead delay - * for 10ms after the deassertion. + * for 50us between and 10ms after the deassertion. */ ctrl = E1000_READ_REG(hw, CTRL); E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST); @@ -2994,12 +3554,15 @@ em_phy_hw_reset(struct em_hw *hw) 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); + em_swfw_sync_release(hw, swfw); } else { /* Read the Extended Device Control Register, assert the PHY_RESET_DIR * bit to put the PHY into reset. Then, take it out of reset. @@ -3026,6 +3589,7 @@ em_phy_hw_reset(struct em_hw *hw) /* Wait for FW to finish PHY configuration. */ ret_val = em_get_phy_cfg_done(hw); + em_release_software_semaphore(hw); return ret_val; } @@ -3103,6 +3667,15 @@ em_detect_gig_phy(struct em_hw *hw) return E1000_SUCCESS; } + /* ESB-2 PHY reads require em_phy_gg82563 to be set because of a work- + * around that forces PHY page 0 to be set or the reads fail. The rest of + * the code in this routine uses em_read_phy_reg to read the PHY ID. + * So for ESB-2 we need to have this set so our reads won't fail. If the + * attached PHY is not a em_phy_gg82563, the routines below will figure + * this out as well. */ + if (hw->mac_type == em_80003es2lan) + hw->phy_type = em_phy_gg82563; + /* 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) @@ -3140,6 +3713,9 @@ em_detect_gig_phy(struct em_hw *hw) case em_82573: 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; default: DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type); return -E1000_ERR_CONFIG; @@ -3166,8 +3742,10 @@ em_phy_reset_dsp(struct em_hw *hw) DEBUGFUNC("em_phy_reset_dsp"); do { - ret_val = em_write_phy_reg(hw, 29, 0x001d); - if(ret_val) break; + if (hw->phy_type != em_phy_gg82563) { + ret_val = em_write_phy_reg(hw, 29, 0x001d); + if(ret_val) break; + } ret_val = em_write_phy_reg(hw, 30, 0x00c1); if(ret_val) break; ret_val = em_write_phy_reg(hw, 30, 0x0000); @@ -3299,8 +3877,17 @@ em_phy_m88_get_info(struct em_hw *hw, /* Cable Length Estimation and Local/Remote Receiver Information * are only valid at 1000 Mbps. */ - phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT); + if (hw->phy_type != em_phy_gg82563) { + phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> + M88E1000_PSSR_CABLE_LENGTH_SHIFT); + } else { + ret_val = em_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE, + &phy_data); + if (ret_val) + return ret_val; + + phy_info->cable_length = phy_data & GG82563_DSPD_CABLE_LENGTH; + } ret_val = em_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); if(ret_val) @@ -3381,7 +3968,8 @@ em_validate_mdi_setting(struct em_hw *hw) /****************************************************************************** * Sets up eeprom variables in the hw struct. Must be called after mac_type - * is configured. + * is configured. Additionally, if this is ICH8, the flash controller GbE + * registers must be mapped, or this will crash. * * hw - Struct containing variables accessed by shared code *****************************************************************************/ @@ -3494,6 +4082,20 @@ em_init_eeprom_params(struct em_hw *hw) E1000_WRITE_REG(hw, EECD, eecd); } break; + case em_80003es2lan: + eeprom->type = em_eeprom_spi; + eeprom->opcode_bits = 8; + eeprom->delay_usec = 1; + if (eecd & E1000_EECD_ADDR_BITS) { + eeprom->page_size = 32; + eeprom->address_bits = 16; + } else { + eeprom->page_size = 8; + eeprom->address_bits = 8; + } + eeprom->use_eerd = TRUE; + eeprom->use_eewr = FALSE; + break; default: break; } @@ -3674,9 +4276,8 @@ em_acquire_eeprom(struct em_hw *hw) DEBUGFUNC("em_acquire_eeprom"); - if(em_get_hw_eeprom_semaphore(hw)) - return -E1000_ERR_EEPROM; - + if (em_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM)) + return -E1000_ERR_SWFW_SYNC; eecd = E1000_READ_REG(hw, EECD); if (hw->mac_type != em_82573) { @@ -3695,7 +4296,7 @@ em_acquire_eeprom(struct em_hw *hw) eecd &= ~E1000_EECD_REQ; E1000_WRITE_REG(hw, EECD, eecd); DEBUGOUT("Could not acquire EEPROM grant\n"); - em_put_hw_eeprom_semaphore(hw); + em_swfw_sync_release(hw, E1000_SWFW_EEP_SM); return -E1000_ERR_EEPROM; } } @@ -3818,7 +4419,7 @@ em_release_eeprom(struct em_hw *hw) E1000_WRITE_REG(hw, EECD, eecd); } - em_put_hw_eeprom_semaphore(hw); + em_swfw_sync_release(hw, E1000_SWFW_EEP_SM); } /****************************************************************************** @@ -3893,17 +4494,21 @@ em_read_eeprom(struct em_hw *hw, return -E1000_ERR_EEPROM; } - /* FLASH reads without acquiring the semaphore are safe in 82573-based - * controllers. - */ - if ((em_is_onboard_nvm_eeprom(hw) == TRUE) || - (hw->mac_type != em_82573)) { - /* Prepare the EEPROM for reading */ - if(em_acquire_eeprom(hw) != E1000_SUCCESS) - return -E1000_ERR_EEPROM; + /* FLASH reads without acquiring the semaphore are safe */ + if (em_is_onboard_nvm_eeprom(hw) == TRUE && + hw->eeprom.use_eerd == FALSE) { + switch (hw->mac_type) { + case em_80003es2lan: + break; + default: + /* Prepare the EEPROM for reading */ + if (em_acquire_eeprom(hw) != E1000_SUCCESS) + return -E1000_ERR_EEPROM; + break; + } } - if(eeprom->use_eerd == TRUE) { + if (eeprom->use_eerd == TRUE) { ret_val = em_read_eeprom_eerd(hw, offset, words, data); if ((em_is_onboard_nvm_eeprom(hw) == TRUE) || (hw->mac_type != em_82573)) @@ -4012,6 +4617,9 @@ em_write_eeprom_eewr(struct em_hw *hw, uint32_t i = 0; int32_t error = 0; + if (em_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM)) + 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) | @@ -4031,6 +4639,7 @@ em_write_eeprom_eewr(struct em_hw *hw, } } + em_swfw_sync_release(hw, E1000_SWFW_EEP_SM); return error; } @@ -4072,6 +4681,8 @@ em_is_onboard_nvm_eeprom(struct em_hw *hw) { uint32_t eecd = 0; + DEBUGFUNC("em_is_onboard_nvm_eeprom"); + if(hw->mac_type == em_82573) { eecd = E1000_READ_REG(hw, EECD); @@ -4410,7 +5021,7 @@ em_commit_shadow_ram(struct em_hw *hw) return -E1000_ERR_EEPROM; } - /* If STM opcode located in bits 15:8 of flop, reset firmware */ + /* If STM opcode located in bits 15:8 of flop, reset firmware */ if ((flop & 0xFF00) == E1000_STM_OPCODE) { E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET); } @@ -4418,7 +5029,7 @@ em_commit_shadow_ram(struct em_hw *hw) /* Perform the flash update */ E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD); - for (i=0; i < attempts; i++) { + for (i=0; i < attempts; i++) { eecd = E1000_READ_REG(hw, EECD); if ((eecd & E1000_EECD_FLUPD) == 0) { break; @@ -4498,6 +5109,7 @@ em_read_mac_addr(struct em_hw * hw) case em_82546: case em_82546_rev_3: case em_82571: + case em_80003es2lan: if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) hw->perm_mac_addr[5] ^= 0x01; break; @@ -4734,8 +5346,37 @@ em_rar_set(struct em_hw *hw, rar_low = ((uint32_t) addr[0] | ((uint32_t) addr[1] << 8) | ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24)); + rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8)); - rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8) | E1000_RAH_AV); + /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx + * unit hang. + * + * Description: + * If there are any Rx frames queued up or otherwise present in the HW + * before RSS is enabled, and then we enable RSS, the HW Rx unit will + * hang. To work around this issue, we have to disable receives and + * flush out all Rx frames before we enable RSS. To do so, we modify we + * redirect all Rx traffic to manageability and then reset the HW. + * This flushes away Rx frames, and (since the redirections to + * manageability persists across resets) keeps new ones from coming in + * while we work. Then, we clear the Address Valid AV bit for all MAC + * addresses and undo the re-direction to manageability. + * Now, frames are coming in again, but the MAC won't accept them, so + * far so good. We now proceed to initialize RSS (if necessary) and + * configure the Rx unit. Last, we re-enable the AV bits and continue + * on our merry way. + */ + switch (hw->mac_type) { + case em_82571: + case em_82572: + case em_80003es2lan: + if (hw->leave_av_bit_off == TRUE) + break; + default: + /* Indicate to hardware the Address is Valid. */ + rar_high |= E1000_RAH_AV; + break; + } E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low); E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high); @@ -4901,7 +5542,7 @@ em_setup_led(struct em_hw *hw) ~IGP01E1000_GMII_SPD)); if(ret_val) return ret_val; - /* FALLTHROUGH */ + /* Fall Through */ default: if(hw->media_type == em_media_type_fiber) { ledctl = E1000_READ_REG(hw, LEDCTL); @@ -4950,7 +5591,7 @@ em_cleanup_led(struct em_hw *hw) hw->phy_spd_default); if(ret_val) return ret_val; - /* FALLTHROUGH */ + /* Fall Through */ default: /* Restore LEDCTL settings */ E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default); @@ -5315,6 +5956,7 @@ em_get_bus_info(struct em_hw *hw) hw->bus_width = em_bus_width_pciex_1; break; case em_82571: + case em_80003es2lan: hw->bus_type = em_bus_type_pci_express; hw->bus_speed = em_bus_speed_2500; hw->bus_width = em_bus_width_pciex_4; @@ -5457,6 +6099,34 @@ em_get_cable_length(struct em_hw *hw, return -E1000_ERR_PHY; break; } + } else if (hw->phy_type == em_phy_gg82563) { + ret_val = em_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE, + &phy_data); + if (ret_val) + return ret_val; + cable_length = phy_data & GG82563_DSPD_CABLE_LENGTH; + + switch (cable_length) { + case em_gg_cable_length_60: + *min_length = 0; + *max_length = em_igp_cable_length_60; + break; + case em_gg_cable_length_60_115: + *min_length = em_igp_cable_length_60; + *max_length = em_igp_cable_length_115; + break; + case em_gg_cable_length_115_150: + *min_length = em_igp_cable_length_115; + *max_length = em_igp_cable_length_150; + break; + case em_gg_cable_length_150: + *min_length = em_igp_cable_length_150; + *max_length = em_igp_cable_length_180; + break; + default: + return -E1000_ERR_PHY; + break; + } } else if(hw->phy_type == em_phy_igp) { /* For IGP PHY */ uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {IGP01E1000_PHY_AGC_A, @@ -5566,7 +6236,8 @@ em_check_polarity(struct em_hw *hw, DEBUGFUNC("em_check_polarity"); - if(hw->phy_type == em_phy_m88) { + if ((hw->phy_type == em_phy_m88) || + (hw->phy_type == em_phy_gg82563)) { /* return the Polarity bit in the Status register. */ ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); @@ -5635,7 +6306,8 @@ em_check_downshift(struct em_hw *hw) return ret_val; hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; - } else if(hw->phy_type == em_phy_m88) { + } else if ((hw->phy_type == em_phy_m88) || + (hw->phy_type == em_phy_gg82563)) { ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if(ret_val) @@ -6666,6 +7338,7 @@ em_get_auto_rd_done(struct em_hw *hw) case em_82571: case em_82572: case em_82573: + case em_80003es2lan: while(timeout) { if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break; else msec_delay(1); @@ -6709,6 +7382,11 @@ em_get_phy_cfg_done(struct em_hw *hw) default: msec_delay(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 */ case em_82571: case em_82572: while (timeout) { @@ -6751,6 +7429,11 @@ em_get_hw_eeprom_semaphore(struct em_hw *hw) if(!hw->eeprom_semaphore_present) return E1000_SUCCESS; + if (hw->mac_type == em_80003es2lan) { + /* Get the SW semaphore. */ + if (em_get_software_semaphore(hw) != E1000_SUCCESS) + return -E1000_ERR_EEPROM; + } /* Get the FW semaphore. */ timeout = hw->eeprom.word_size + 1; @@ -6796,10 +7479,75 @@ em_put_hw_eeprom_semaphore(struct em_hw *hw) return; swsm = E1000_READ_REG(hw, SWSM); + if (hw->mac_type == em_80003es2lan) { + /* Release both semaphores. */ + swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); + } else swsm &= ~(E1000_SWSM_SWESMBI); E1000_WRITE_REG(hw, SWSM, swsm); } +/*************************************************************************** + * + * Obtaining software semaphore bit (SMBI) before resetting PHY. + * + * hw: Struct containing variables accessed by shared code + * + * returns: - E1000_ERR_RESET if fail to obtain semaphore. + * E1000_SUCCESS at any other case. + * + ***************************************************************************/ +int32_t +em_get_software_semaphore(struct em_hw *hw) +{ + int32_t timeout = hw->eeprom.word_size + 1; + uint32_t swsm; + + DEBUGFUNC("em_get_software_semaphore"); + + if (hw->mac_type != em_80003es2lan) + return E1000_SUCCESS; + + 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)) + break; + msec_delay_irq(1); + timeout--; + } + + if(!timeout) { + DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); + return -E1000_ERR_RESET; + } + + return E1000_SUCCESS; +} + +/*************************************************************************** + * + * Release semaphore bit (SMBI). + * + * hw: Struct containing variables accessed by shared code + * + ***************************************************************************/ +void +em_release_software_semaphore(struct em_hw *hw) +{ + uint32_t swsm; + + DEBUGFUNC("em_release_software_semaphore"); + + if (hw->mac_type != em_80003es2lan) + return; + + swsm = E1000_READ_REG(hw, SWSM); + /* Release the SW semaphores.*/ + swsm &= ~E1000_SWSM_SMBI; + E1000_WRITE_REG(hw, SWSM, swsm); +} + /****************************************************************************** * Checks if PHY reset is blocked due to SOL/IDER session, for example. * Returning E1000_BLK_PHY_RESET isn't necessarily an error. But it's up to @@ -6836,6 +7584,7 @@ em_arc_subsystem_valid(struct em_hw *hw) case em_82571: case em_82572: case em_82573: + case em_80003es2lan: fwsm = E1000_READ_REG(hw, FWSM); if((fwsm & E1000_FWSM_MODE_MASK) != 0) return TRUE; diff --git a/sys/dev/pci/if_em_hw.h b/sys/dev/pci/if_em_hw.h index 9d897341433..704d61bd0c2 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.11 2005/11/08 01:33:19 brad Exp $ */ +/* $OpenBSD: if_em_hw.h,v 1.12 2006/03/28 05:33:03 brad Exp $ */ /* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */ /* if_em_hw.h @@ -67,6 +67,7 @@ typedef enum { em_82571, em_82572, em_82573, + em_80003es2lan, em_num_macs } em_mac_type; @@ -146,6 +147,13 @@ typedef enum { } em_cable_length; typedef enum { + em_gg_cable_length_60 = 0, + em_gg_cable_length_60_115 = 1, + em_gg_cable_length_115_150 = 2, + em_gg_cable_length_150 = 4 +} em_gg_cable_length; + +typedef enum { em_igp_cable_length_10 = 10, em_igp_cable_length_20 = 20, em_igp_cable_length_30 = 30, @@ -215,6 +223,7 @@ typedef enum { em_phy_m88 = 0, em_phy_igp, em_phy_igp_2, + em_phy_gg82563, em_phy_undefined = 0xFF } em_phy_type; @@ -286,6 +295,7 @@ typedef enum { #define E1000_ERR_MASTER_REQUESTS_PENDING 10 #define E1000_ERR_HOST_INTERFACE_COMMAND 11 #define E1000_BLK_PHY_RESET 12 +#define E1000_ERR_SWFW_SYNC 13 /* Function prototypes */ /* Initialization */ @@ -318,6 +328,9 @@ int32_t em_get_cable_length(struct em_hw *hw, uint16_t *min_length, uint16_t *ma int32_t em_check_polarity(struct em_hw *hw, uint16_t *polarity); 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); @@ -358,13 +371,13 @@ struct em_host_mng_command_info { }; struct em_host_mng_dhcp_cookie{ uint32_t signature; - uint16_t vlan_id; - uint8_t reserved0; uint8_t status; + uint8_t reserved0; + uint16_t vlan_id; uint32_t reserved1; - uint8_t checksum; - uint8_t reserved3; uint16_t reserved2; + uint8_t reserved3; + uint8_t checksum; }; int32_t em_mng_write_dhcp_info(struct em_hw *hw, uint8_t *buffer, @@ -433,6 +446,7 @@ int32_t em_get_hw_eeprom_semaphore(struct em_hw *hw); void em_put_hw_eeprom_semaphore(struct em_hw *hw); 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); #ifndef E1000_READ_REG_IO #define E1000_READ_REG_IO(a, reg) \ @@ -474,6 +488,7 @@ uint8_t em_arc_subsystem_valid(struct em_hw *hw); #define E1000_DEV_ID_82546GB_FIBER 0x107A #define E1000_DEV_ID_82546GB_SERDES 0x107B #define E1000_DEV_ID_82546GB_PCIE 0x108A +#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099 #define E1000_DEV_ID_82547EI 0x1019 #define E1000_DEV_ID_82547EI_MOBILE 0x101A #define E1000_DEV_ID_82571EB_COPPER 0x105E @@ -482,11 +497,13 @@ uint8_t em_arc_subsystem_valid(struct em_hw *hw); #define E1000_DEV_ID_82572EI_COPPER 0x107D #define E1000_DEV_ID_82572EI_FIBER 0x107E #define E1000_DEV_ID_82572EI_SERDES 0x107F +#define E1000_DEV_ID_82572EI 0x10B9 #define E1000_DEV_ID_82573E 0x108B #define E1000_DEV_ID_82573E_IAMT 0x108C #define E1000_DEV_ID_82573L 0x109A - -#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099 +#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 NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 @@ -879,6 +896,7 @@ struct em_ffvt_entry { #define E1000_TXCW 0x00178 /* TX Configuration Word - RW */ #define E1000_RXCW 0x00180 /* RX Configuration Word - RO */ #define E1000_TCTL 0x00400 /* TX Control - RW */ +#define E1000_TCTL_EXT 0x00404 /* Extended TX Control - RW */ #define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */ #define E1000_TBT 0x00448 /* TX Burst Timer - RW */ #define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ @@ -1025,6 +1043,11 @@ struct em_ffvt_entry { #define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ #define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ +#define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */ +#define E1000_MDPHYA 0x0003C /* PHY address - RW */ +#define E1000_MANC2H 0x05860 /* Managment Control To Host - RW */ +#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */ + #define E1000_GCR 0x05B00 /* PCI-Ex Control */ #define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */ #define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */ @@ -1094,6 +1117,7 @@ struct em_ffvt_entry { #define E1000_82542_RXCW E1000_RXCW #define E1000_82542_MTA 0x00200 #define E1000_82542_TCTL E1000_TCTL +#define E1000_82542_TCTL_EXT E1000_TCTL_EXT #define E1000_82542_TIPG E1000_TIPG #define E1000_82542_TDBAL 0x00420 #define E1000_82542_TDBAH 0x00424 @@ -1241,6 +1265,8 @@ struct em_ffvt_entry { #define E1000_82542_RSSRK E1000_RSSRK #define E1000_82542_RSSIM E1000_RSSIM #define E1000_82542_RSSIR E1000_RSSIR +#define E1000_82542_KUMCTRLSTA E1000_KUMCTRLSTA +#define E1000_82542_SW_FW_SYNC E1000_SW_FW_SYNC /* Statistics counters collected by the MAC */ struct em_hw_stats { @@ -1332,6 +1358,7 @@ struct em_hw { em_ffe_config ffe_config_state; uint32_t asf_firmware_present; uint32_t eeprom_semaphore_present; + uint32_t swfw_sync_present; unsigned long io_base; uint32_t phy_id; uint32_t phy_revision; @@ -1390,6 +1417,7 @@ struct em_hw { boolean_t ifs_params_forced; boolean_t in_ifs_mode; boolean_t mng_reg_access_disabled; + boolean_t leave_av_bit_off; }; #define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */ @@ -1421,6 +1449,8 @@ struct em_hw { #define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ #define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */ #define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */ +#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */ +#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */ #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ #define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ @@ -1457,6 +1487,16 @@ struct em_hw { #define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ #define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ #define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ +#define E1000_STATUS_BMC_SKU_0 0x00100000 /* BMC USB redirect disabled */ +#define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */ +#define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */ +#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */ +#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution disabled */ +#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */ +#define E1000_STATUS_FUSE_8 0x04000000 +#define E1000_STATUS_FUSE_9 0x08000000 +#define E1000_STATUS_SERDES0_DIS 0x10000000 /* SERDES disabled on port 0 */ +#define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disabled on port 1 */ /* Constants used to intrepret the masked PCI-X bus speed. */ #define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ @@ -1530,9 +1570,12 @@ struct em_hw { #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ #define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ #define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ +#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 #define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 +#define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000 +#define E1000_CTRL_EXT_LINK_MODE_SERDES 0x00C00000 #define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000 #define E1000_CTRL_EXT_WR_WMARK_256 0x00000000 #define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 @@ -1542,6 +1585,9 @@ struct em_hw { #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 */ +#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error detection enabled */ +#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */ +#define E1000_CTRL_EXT_GHOST_PAREN 0x40000000 /* MDI Control */ #define E1000_MDIC_DATA_MASK 0x0000FFFF @@ -1555,6 +1601,32 @@ struct em_hw { #define E1000_MDIC_INT_EN 0x20000000 #define E1000_MDIC_ERROR 0x40000000 +#define E1000_KUMCTRLSTA_MASK 0x0000FFFF +#define E1000_KUMCTRLSTA_OFFSET 0x001F0000 +#define E1000_KUMCTRLSTA_OFFSET_SHIFT 16 +#define E1000_KUMCTRLSTA_REN 0x00200000 + +#define E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL 0x00000000 +#define E1000_KUMCTRLSTA_OFFSET_CTRL 0x00000001 +#define E1000_KUMCTRLSTA_OFFSET_INB_CTRL 0x00000002 +#define E1000_KUMCTRLSTA_OFFSET_DIAG 0x00000003 +#define E1000_KUMCTRLSTA_OFFSET_TIMEOUTS 0x00000004 +#define E1000_KUMCTRLSTA_OFFSET_INB_PARAM 0x00000009 +#define E1000_KUMCTRLSTA_OFFSET_HD_CTRL 0x00000010 +#define E1000_KUMCTRLSTA_OFFSET_M2P_SERDES 0x0000001E +#define E1000_KUMCTRLSTA_OFFSET_M2P_MODES 0x0000001F + +/* FIFO Control */ +#define E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS 0x00000008 +#define E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS 0x00000800 + +/* In-Band Control */ +#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 + /* LED Control */ #define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F #define E1000_LEDCTL_LED0_MODE_SHIFT 0 @@ -1617,6 +1689,13 @@ struct em_hw { #define E1000_ICR_MNG 0x00040000 /* Manageability event */ #define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ #define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ +#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity error */ +#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */ +#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 */ /* Interrupt Cause Set */ #define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1637,6 +1716,12 @@ struct em_hw { #define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ +#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 */ /* Interrupt Mask Set */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1657,6 +1742,12 @@ struct em_hw { #define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ +#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 */ /* Interrupt Mask Clear */ #define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1677,6 +1768,12 @@ struct em_hw { #define E1000_IMC_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_IMC_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_IMC_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_IMC_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_IMC_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_IMC_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ +#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 */ /* Receive Control */ #define E1000_RCTL_RST 0x00000001 /* Software reset */ @@ -1746,6 +1843,12 @@ struct em_hw { #define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */ #define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */ +/* SW_W_SYNC definitions */ +#define E1000_SWFW_EEP_SM 0x0001 +#define E1000_SWFW_PHY0_SM 0x0002 +#define E1000_SWFW_PHY1_SM 0x0004 +#define E1000_SWFW_MAC_CSR_SM 0x0008 + /* Receive Descriptor */ #define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ #define E1000_RDT_FPDB 0x80000000 /* Flush descriptor block */ @@ -1791,7 +1894,6 @@ struct em_hw { #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ #define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc. still to be processed. */ - /* Transmit Configuration Word */ #define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ #define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */ @@ -1825,6 +1927,11 @@ struct em_hw { #define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ #define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */ #define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ +/* Extended Transmit Control */ +#define E1000_TCTL_EXT_BST_MASK 0x000003FF /* Backoff Slot Time */ +#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */ + +#define DEFAULT_80003ES2LAN_TCTL_EXT_GCEX 0x00010000 /* Receive Checksum Control */ #define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */ @@ -1902,6 +2009,7 @@ struct em_hw { #define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */ #define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ #define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */ +#define E1000_MANC_RCV_ALL 0x00080000 /* Receive All Enabled */ #define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ #define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MAC address * filtering */ @@ -1987,6 +2095,23 @@ struct em_host_command_info { #define E1000_MDALIGN 4096 +/* PCI-Ex registers*/ + +/* PCI-Ex Control Register */ +#define E1000_GCR_RXD_NO_SNOOP 0x00000001 +#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 +#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004 +#define E1000_GCR_TXD_NO_SNOOP 0x00000008 +#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 +#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 + +#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ + E1000_GCR_RXDSCW_NO_SNOOP | \ + E1000_GCR_RXDSCR_NO_SNOOP | \ + E1000_GCR_TXD_NO_SNOOP | \ + E1000_GCR_TXDSCW_NO_SNOOP | \ + E1000_GCR_TXDSCR_NO_SNOOP) + #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 /* Function Active and Power State to MNG */ #define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003 @@ -2046,12 +2171,14 @@ struct em_host_command_info { #define EEPROM_INIT_CONTROL1_REG 0x000A #define EEPROM_INIT_CONTROL2_REG 0x000F #define EEPROM_INIT_CONTROL3_PORT_B 0x0014 +#define EEPROM_INIT_3GIO_3 0x001A #define EEPROM_INIT_CONTROL3_PORT_A 0x0024 #define EEPROM_CFG 0x0012 #define EEPROM_FLASH_VERSION 0x0032 #define EEPROM_CHECKSUM_REG 0x003F #define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */ +#define E1000_EEPROM_CFG_DONE_PORT_1 0x00080000 /* ...for second port */ /* Word definitions for ID LED Settings */ #define ID_LED_RESERVED_0000 0x0000 @@ -2094,6 +2221,9 @@ struct em_host_command_info { #define EEPROM_WORD0F_ANE 0x0800 #define EEPROM_WORD0F_SWPDIO_EXT 0x00F0 +/* Mask bits for fields in Word 0x1a of the EEPROM */ +#define EEPROM_WORD1A_ASPM_MASK 0x000C + /* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */ #define EEPROM_SUM 0xBABA @@ -2109,7 +2239,10 @@ struct em_host_command_info { /* Collision related configuration parameters */ #define E1000_COLLISION_THRESHOLD 15 #define E1000_CT_SHIFT 4 -#define E1000_COLLISION_DISTANCE 64 +/* Collision distance is a 0-based value that applies to + * half-duplex-capable hardware only. */ +#define E1000_COLLISION_DISTANCE 63 +#define E1000_COLLISION_DISTANCE_82542 64 #define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE #define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE #define E1000_COLD_SHIFT 12 @@ -2133,8 +2266,11 @@ struct em_host_command_info { #define DEFAULT_82542_TIPG_IPGR2 10 #define DEFAULT_82543_TIPG_IPGR2 6 +#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7 #define E1000_TIPG_IPGR2_SHIFT 20 +#define DEFAULT_80003ES2LAN_TIPG_IPGT_10_100 0x00000009 +#define DEFAULT_80003ES2LAN_TIPG_IPGT_1000 0x00000008 #define E1000_TXDMAC_DPP 0x00000001 /* Adaptive IFS defines */ @@ -2372,6 +2508,79 @@ struct em_host_command_info { #define IGP01E1000_ANALOG_REGS_PAGE 0x20C0 +/* Bits... + * 15-5: page + * 4-0: register offset + */ +#define GG82563_PAGE_SHIFT 5 +#define GG82563_REG(page, reg) \ + (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS)) +#define GG82563_MIN_ALT_REG 30 + +/* GG82563 Specific Registers */ +#define GG82563_PHY_SPEC_CTRL \ + GG82563_REG(0, 16) /* PHY Specific Control */ +#define GG82563_PHY_SPEC_STATUS \ + GG82563_REG(0, 17) /* PHY Specific Status */ +#define GG82563_PHY_INT_ENABLE \ + GG82563_REG(0, 18) /* Interrupt Enable */ +#define GG82563_PHY_SPEC_STATUS_2 \ + GG82563_REG(0, 19) /* PHY Specific Status 2 */ +#define GG82563_PHY_RX_ERR_CNTR \ + GG82563_REG(0, 21) /* Receive Error Counter */ +#define GG82563_PHY_PAGE_SELECT \ + GG82563_REG(0, 22) /* Page Select */ +#define GG82563_PHY_SPEC_CTRL_2 \ + GG82563_REG(0, 26) /* PHY Specific Control 2 */ +#define GG82563_PHY_PAGE_SELECT_ALT \ + GG82563_REG(0, 29) /* Alternate Page Select */ +#define GG82563_PHY_TEST_CLK_CTRL \ + GG82563_REG(0, 30) /* Test Clock Control (use reg. 29 to select) */ + +#define GG82563_PHY_MAC_SPEC_CTRL \ + GG82563_REG(2, 21) /* MAC Specific Control Register */ +#define GG82563_PHY_MAC_SPEC_CTRL_2 \ + GG82563_REG(2, 26) /* MAC Specific Control 2 */ + +#define GG82563_PHY_DSP_DISTANCE \ + GG82563_REG(5, 26) /* DSP Distance */ + +/* Page 193 - Port Control Registers */ +#define GG82563_PHY_KMRN_MODE_CTRL \ + GG82563_REG(193, 16) /* Kumeran Mode Control */ +#define GG82563_PHY_PORT_RESET \ + GG82563_REG(193, 17) /* Port Reset */ +#define GG82563_PHY_REVISION_ID \ + GG82563_REG(193, 18) /* Revision ID */ +#define GG82563_PHY_DEVICE_ID \ + GG82563_REG(193, 19) /* Device ID */ +#define GG82563_PHY_PWR_MGMT_CTRL \ + GG82563_REG(193, 20) /* Power Management Control */ +#define GG82563_PHY_RATE_ADAPT_CTRL \ + GG82563_REG(193, 25) /* Rate Adaptation Control */ + +/* Page 194 - KMRN Registers */ +#define GG82563_PHY_KMRN_FIFO_CTRL_STAT \ + GG82563_REG(194, 16) /* FIFO's Control/Status */ +#define GG82563_PHY_KMRN_CTRL \ + GG82563_REG(194, 17) /* Control */ +#define GG82563_PHY_INBAND_CTRL \ + GG82563_REG(194, 18) /* Inband Control */ +#define GG82563_PHY_KMRN_DIAGNOSTIC \ + GG82563_REG(194, 19) /* Diagnostic */ +#define GG82563_PHY_ACK_TIMEOUTS \ + GG82563_REG(194, 20) /* Acknowledge Timeouts */ +#define GG82563_PHY_ADV_ABILITY \ + GG82563_REG(194, 21) /* Advertised Ability */ +#define GG82563_PHY_LINK_PARTNER_ADV_ABILITY \ + GG82563_REG(194, 23) /* Link Partner Advertised Ability */ +#define GG82563_PHY_ADV_NEXT_PAGE \ + GG82563_REG(194, 24) /* Advertised Next Page */ +#define GG82563_PHY_LINK_PARTNER_ADV_NEXT_PAGE \ + GG82563_REG(194, 25) /* Link Partner Advertised Next page */ +#define GG82563_PHY_KMRN_MISC \ + GG82563_REG(194, 26) /* Misc. */ + /* PHY Control Register */ #define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ #define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ @@ -2684,6 +2893,113 @@ struct em_host_command_info { #define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080 #define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500 +/* GG82563 PHY Specific Status Register (Page 0, Register 16 */ +#define GG82563_PSCR_DISABLE_JABBER 0x0001 /* 1=Disable Jabber */ +#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Polarity Reversal Disabled */ +#define GG82563_PSCR_POWER_DOWN 0x0004 /* 1=Power Down */ +#define GG82563_PSCR_COPPER_TRANSMITER_DISABLE 0x0008 /* 1=Transmitter Disabled */ +#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060 +#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI configuration */ +#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX configuration */ +#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Automatic crossover */ +#define GG82563_PSCR_ENALBE_EXTENDED_DISTANCE 0x0080 /* 1=Enable Extended Distance */ +#define GG82563_PSCR_ENERGY_DETECT_MASK 0x0300 +#define GG82563_PSCR_ENERGY_DETECT_OFF 0x0000 /* 00,01=Off */ +#define GG82563_PSCR_ENERGY_DETECT_RX 0x0200 /* 10=Sense on Rx only (Energy Detect) */ +#define GG82563_PSCR_ENERGY_DETECT_RX_TM 0x0300 /* 11=Sense and Tx NLP */ +#define GG82563_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force Link Good */ +#define GG82563_PSCR_DOWNSHIFT_ENABLE 0x0800 /* 1=Enable Downshift */ +#define GG82563_PSCR_DOWNSHIFT_COUNTER_MASK 0x7000 +#define GG82563_PSCR_DOWNSHIFT_COUNTER_SHIFT 12 + +/* PHY Specific Status Register (Page 0, Register 17) */ +#define GG82563_PSSR_JABBER 0x0001 /* 1=Jabber */ +#define GG82563_PSSR_POLARITY 0x0002 /* 1=Polarity Reversed */ +#define GG82563_PSSR_LINK 0x0008 /* 1=Link is Up */ +#define GG82563_PSSR_ENERGY_DETECT 0x0010 /* 1=Sleep, 0=Active */ +#define GG82563_PSSR_DOWNSHIFT 0x0020 /* 1=Downshift */ +#define GG82563_PSSR_CROSSOVER_STATUS 0x0040 /* 1=MDIX, 0=MDI */ +#define GG82563_PSSR_RX_PAUSE_ENABLED 0x0100 /* 1=Receive Pause Enabled */ +#define GG82563_PSSR_TX_PAUSE_ENABLED 0x0200 /* 1=Transmit Pause Enabled */ +#define GG82563_PSSR_LINK_UP 0x0400 /* 1=Link Up */ +#define GG82563_PSSR_SPEED_DUPLEX_RESOLVED 0x0800 /* 1=Resolved */ +#define GG82563_PSSR_PAGE_RECEIVED 0x1000 /* 1=Page Received */ +#define GG82563_PSSR_DUPLEX 0x2000 /* 1-Full-Duplex */ +#define GG82563_PSSR_SPEED_MASK 0xC000 +#define GG82563_PSSR_SPEED_10MBPS 0x0000 /* 00=10Mbps */ +#define GG82563_PSSR_SPEED_100MBPS 0x4000 /* 01=100Mbps */ +#define GG82563_PSSR_SPEED_1000MBPS 0x8000 /* 10=1000Mbps */ + +/* PHY Specific Status Register 2 (Page 0, Register 19) */ +#define GG82563_PSSR2_JABBER 0x0001 /* 1=Jabber */ +#define GG82563_PSSR2_POLARITY_CHANGED 0x0002 /* 1=Polarity Changed */ +#define GG82563_PSSR2_ENERGY_DETECT_CHANGED 0x0010 /* 1=Energy Detect Changed */ +#define GG82563_PSSR2_DOWNSHIFT_INTERRUPT 0x0020 /* 1=Downshift Detected */ +#define GG82563_PSSR2_MDI_CROSSOVER_CHANGE 0x0040 /* 1=Crossover Changed */ +#define GG82563_PSSR2_FALSE_CARRIER 0x0100 /* 1=False Carrier */ +#define GG82563_PSSR2_SYMBOL_ERROR 0x0200 /* 1=Symbol Error */ +#define GG82563_PSSR2_LINK_STATUS_CHANGED 0x0400 /* 1=Link Status Changed */ +#define GG82563_PSSR2_AUTO_NEG_COMPLETED 0x0800 /* 1=Auto-Neg Completed */ +#define GG82563_PSSR2_PAGE_RECEIVED 0x1000 /* 1=Page Received */ +#define GG82563_PSSR2_DUPLEX_CHANGED 0x2000 /* 1=Duplex Changed */ +#define GG82563_PSSR2_SPEED_CHANGED 0x4000 /* 1=Speed Changed */ +#define GG82563_PSSR2_AUTO_NEG_ERROR 0x8000 /* 1=Auto-Neg Error */ + +/* PHY Specific Control Register 2 (Page 0, Register 26) */ +#define GG82563_PSCR2_10BT_POLARITY_FORCE 0x0002 /* 1=Force Negative Polarity */ +#define GG82563_PSCR2_1000MB_TEST_SELECT_MASK 0x000C +#define GG82563_PSCR2_1000MB_TEST_SELECT_NORMAL 0x0000 /* 00,01=Normal Operation */ +#define GG82563_PSCR2_1000MB_TEST_SELECT_112NS 0x0008 /* 10=Select 112ns Sequence */ +#define GG82563_PSCR2_1000MB_TEST_SELECT_16NS 0x000C /* 11=Select 16ns Sequence */ +#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 /* 1=Reverse Auto-Negotiation */ +#define GG82563_PSCR2_1000BT_DISABLE 0x4000 /* 1=Disable 1000BASE-T */ +#define GG82563_PSCR2_TRANSMITER_TYPE_MASK 0x8000 +#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_B 0x0000 /* 0=Class B */ +#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_A 0x8000 /* 1=Class A */ + +/* MAC Specific Control Register (Page 2, Register 21) */ +/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */ +#define GG82563_MSCR_TX_CLK_MASK 0x0007 +#define GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ 0x0004 +#define GG82563_MSCR_TX_CLK_100MBPS_25MHZ 0x0005 +#define GG82563_MSCR_TX_CLK_1000MBPS_2_5MHZ 0x0006 +#define GG82563_MSCR_TX_CLK_1000MBPS_25MHZ 0x0007 + +#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */ + +/* 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 */ + +/* Kumeran Mode Control Register (Page 193, Register 16) */ +#define GG82563_KMCR_PHY_LEDS_EN 0x0020 /* 1=PHY LEDs, 0=Kumeran Inband LEDs */ +#define GG82563_KMCR_FORCE_LINK_UP 0x0040 /* 1=Force Link Up */ +#define GG82563_KMCR_SUPPRESS_SGMII_EPD_EXT 0x0080 +#define GG82563_KMCR_MDIO_BUS_SPEED_SELECT_MASK 0x0400 +#define GG82563_KMCR_MDIO_BUS_SPEED_SELECT 0x0400 /* 1=6.25MHz, 0=0.8MHz */ +#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 + +/* Power Management Control Register (Page 193, Register 20) */ +#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 /* 1=Enalbe SERDES Electrical Idle */ +#define GG82563_PMCR_DISABLE_PORT 0x0002 /* 1=Disable Port */ +#define GG82563_PMCR_DISABLE_SERDES 0x0004 /* 1=Disable SERDES */ +#define GG82563_PMCR_REVERSE_AUTO_NEG 0x0008 /* 1=Enable Reverse Auto-Negotiation */ +#define GG82563_PMCR_DISABLE_1000_NON_D0 0x0010 /* 1=Disable 1000Mbps Auto-Neg in non D0 */ +#define GG82563_PMCR_DISABLE_1000 0x0020 /* 1=Disable 1000Mbps Auto-Neg Always */ +#define GG82563_PMCR_REVERSE_AUTO_NEG_D0A 0x0040 /* 1=Enable D0a Reverse Auto-Negotiation */ +#define GG82563_PMCR_FORCE_POWER_STATE 0x0080 /* 1=Force Power State */ +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_MASK 0x0300 +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_DR 0x0000 /* 00=Dr */ +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D0U 0x0100 /* 01=D0u */ +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D0A 0x0200 /* 10=D0a */ +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D3 0x0300 /* 11=D3 */ + +/* In-Band Control Register (Page 194, Register 18) */ +#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding Use */ + /* Bit definitions for valid PHY IDs. */ /* I = Integrated * E = External @@ -2697,6 +3013,7 @@ struct em_host_command_info { #define M88E1011_I_REV_4 0x04 #define M88E1111_I_PHY_ID 0x01410CC0 #define L1LXT971A_PHY_ID 0x001378E0 +#define GG82563_E_PHY_ID 0x01410CA0 /* Miscellaneous PHY bit definitions. */ #define PHY_PREAMBLE 0xFFFFFFFF |