diff options
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_em.c | 38 | ||||
-rw-r--r-- | sys/dev/pci/if_em_hw.c | 110 | ||||
-rw-r--r-- | sys/dev/pci/if_em_hw.h | 32 | ||||
-rw-r--r-- | sys/dev/pci/if_em_osdep.h | 13 |
4 files changed, 139 insertions, 54 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c index b95acfc5f96..0f3619321ca 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.260 2011/08/30 02:51:19 haesbaert Exp $ */ +/* $OpenBSD: if_em.c,v 1.261 2011/10/05 02:52:09 jsg Exp $ */ /* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */ #include <dev/pci/if_em.h> @@ -465,6 +465,30 @@ em_attach(struct device *parent, struct device *self, void *aux) } } + if (sc->hw.mac_type == em_80003es2lan || sc->hw.mac_type == em_82575 || + sc->hw.mac_type == em_82580) { + uint32_t reg = EM_READ_REG(&sc->hw, E1000_STATUS); + sc->hw.bus_func = (reg & E1000_STATUS_FUNC_MASK) >> + E1000_STATUS_FUNC_SHIFT; + + switch (sc->hw.bus_func) { + case 0: + sc->hw.swfw = E1000_SWFW_PHY0_SM; + break; + case 1: + sc->hw.swfw = E1000_SWFW_PHY1_SM; + break; + case 2: + sc->hw.swfw = E1000_SWFW_PHY2_SM; + break; + case 3: + sc->hw.swfw = E1000_SWFW_PHY3_SM; + break; + } + } else { + sc->hw.bus_func = 0; + } + /* Copy the permanent MAC address out of the EEPROM */ if (em_read_mac_addr(&sc->hw) < 0) { printf("%s: EEPROM read error while reading mac address\n", @@ -1814,7 +1838,7 @@ em_setup_interface(struct em_softc *sc) ifp->if_capabilities = IFCAP_VLAN_MTU; #if NVLAN > 0 - if (sc->hw.mac_type != em_82575) + if (sc->hw.mac_type != em_82575 && sc->hw.mac_type != em_82580) ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; #endif @@ -2175,7 +2199,7 @@ em_initialize_transmit_unit(struct em_softc *sc) /* Setup Transmit Descriptor Base Settings */ sc->txd_cmd = E1000_TXD_CMD_IFCS; - if (sc->hw.mac_type == em_82575) { + if (sc->hw.mac_type == em_82575 || sc->hw.mac_type == em_82580) { /* 82575/6 need to enable the TX queue and lack the IDE bit */ reg_tctl = E1000_READ_REG(&sc->hw, TXDCTL); reg_tctl |= E1000_TXDCTL_QUEUE_ENABLE; @@ -2630,6 +2654,14 @@ em_initialize_receive_unit(struct em_softc *sc) if (sc->hw.mac_type == em_82573) E1000_WRITE_REG(&sc->hw, RDTR, 0x20); + if (sc->hw.mac_type == em_82575 || sc->hw.mac_type == em_82580) { + /* 82575/6 need to enable the RX queue */ + uint32_t reg; + reg = E1000_READ_REG(&sc->hw, RXDCTL); + reg |= E1000_RXDCTL_QUEUE_ENABLE; + E1000_WRITE_REG(&sc->hw, RXDCTL, reg); + } + /* Enable Receives */ E1000_WRITE_REG(&sc->hw, RCTL, reg_rctl); diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c index 7ec5f953dda..f73af64cd58 100644 --- a/sys/dev/pci/if_em_hw.c +++ b/sys/dev/pci/if_em_hw.c @@ -31,7 +31,7 @@ *******************************************************************************/ -/* $OpenBSD: if_em_hw.c,v 1.65 2011/05/02 18:16:58 dhill Exp $ */ +/* $OpenBSD: if_em_hw.c,v 1.66 2011/10/05 02:52:10 jsg Exp $ */ /* * if_em_hw.c Shared functions for accessing and configuring the MAC */ @@ -955,6 +955,26 @@ em_reset_hw(struct em_hw *hw) kab |= E1000_KABGTXD_BGSQLBIAS; E1000_WRITE_REG(hw, KABGTXD, kab); } + + if (hw->mac_type == em_82580) { + uint32_t mdicnfg; + uint16_t nvm_data; + + /* clear global device reset status bit */ + EM_WRITE_REG(hw, E1000_STATUS, E1000_STATUS_DEV_RST_SET); + + em_read_eeprom(hw, EEPROM_INIT_CONTROL3_PORT_A + + NVM_82580_LAN_FUNC_OFFSET(hw->bus_func), 1, + &nvm_data); + + mdicnfg = EM_READ_REG(hw, E1000_MDICNFG); + if (nvm_data & NVM_WORD24_EXT_MDIO) + mdicnfg |= E1000_MDICNFG_EXT_MDIO; + if (nvm_data & NVM_WORD24_COM_MDIO) + mdicnfg |= E1000_MDICNFG_COM_MDIO; + EM_WRITE_REG(hw, E1000_MDICNFG, mdicnfg); + } + return E1000_SUCCESS; } @@ -4575,20 +4595,13 @@ int32_t em_write_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t phy_data) { uint32_t ret_val; - uint16_t swfw; DEBUGFUNC("em_write_phy_reg"); if (hw->mac_type == em_pchlan || hw->mac_type == em_pch2lan) return (em_access_phy_reg_hv(hw, reg_addr, &phy_data, FALSE)); - if (((hw->mac_type == em_80003es2lan) || (hw->mac_type == em_82575)) && - (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)) + if (em_swfw_sync_acquire(hw, hw->swfw)) return -E1000_ERR_SWFW_SYNC; if ((hw->phy_type == em_phy_igp || @@ -4598,7 +4611,7 @@ em_write_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t phy_data) 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); + em_swfw_sync_release(hw, hw->swfw); return ret_val; } } else if (hw->phy_type == em_phy_gg82563) { @@ -4623,7 +4636,7 @@ em_write_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t phy_data) } if (ret_val) { - em_swfw_sync_release(hw, swfw); + em_swfw_sync_release(hw, hw->swfw); return ret_val; } } @@ -4639,7 +4652,7 @@ em_write_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t phy_data) ret_val = em_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, phy_data); - em_swfw_sync_release(hw, swfw); + em_swfw_sync_release(hw, hw->swfw); return ret_val; } @@ -4719,16 +4732,9 @@ STATIC 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)) + if (em_swfw_sync_acquire(hw, hw->swfw)) return -E1000_ERR_SWFW_SYNC; /* Write register address */ @@ -4743,7 +4749,7 @@ em_read_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t *data) reg_val = E1000_READ_REG(hw, KUMCTRLSTA); *data = (uint16_t) reg_val; - em_swfw_sync_release(hw, swfw); + em_swfw_sync_release(hw, hw->swfw); return E1000_SUCCESS; } @@ -4751,17 +4757,9 @@ STATIC 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)) + if (em_swfw_sync_acquire(hw, hw->swfw)) return -E1000_ERR_SWFW_SYNC; reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) & @@ -4770,7 +4768,7 @@ em_write_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t data) E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val); usec_delay(2); - em_swfw_sync_release(hw, swfw); + em_swfw_sync_release(hw, hw->swfw); return E1000_SUCCESS; } @@ -4785,7 +4783,6 @@ 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"); /* * In the case of the phy reset being blocked, it's not an error, we @@ -4798,14 +4795,7 @@ em_phy_hw_reset(struct em_hw *hw) DEBUGOUT("Resetting Phy...\n"); if (hw->mac_type > em_82543 && hw->mac_type != em_icp_xxxx) { - if (((hw->mac_type == em_80003es2lan) || - (hw->mac_type == em_82575)) && - (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)) { + if (em_swfw_sync_acquire(hw, hw->swfw)) { DEBUGOUT("Unable to acquire swfw sync\n"); return -E1000_ERR_SWFW_SYNC; } @@ -4831,7 +4821,7 @@ em_phy_hw_reset(struct em_hw *hw) if (hw->mac_type >= em_82571) msec_delay_irq(10); - em_swfw_sync_release(hw, swfw); + em_swfw_sync_release(hw, hw->swfw); /* * the M88E1141_E_PHY_ID might need reset here, but nothing * proves it @@ -5130,8 +5120,16 @@ em_match_gig_phy(struct em_hw *hw) match = TRUE; break; case em_82580: - if (hw->phy_id == I82580_I_PHY_ID) + if (hw->phy_id == I82580_I_PHY_ID) { + uint32_t mdic; + + mdic = EM_READ_REG(hw, E1000_MDICNFG); + mdic &= E1000_MDICNFG_PHY_MASK; + hw->phy_addr = mdic >> E1000_MDICNFG_PHY_SHIFT; + DEBUGOUT1("MDICNFG PHY ADDR %d", + mdic >> E1000_MDICNFG_PHY_SHIFT); match = TRUE; + } break; case em_80003es2lan: if (hw->phy_id == GG82563_E_PHY_ID) @@ -5252,6 +5250,14 @@ em_detect_gig_phy(struct em_hw *hw) if (hw->mac_type == em_80003es2lan) hw->phy_type = em_phy_gg82563; + /* Power on SGMII phy if it is disabled */ + if (hw->mac_type == em_82580) { + uint32_t ctrl_ext = EM_READ_REG(hw, E1000_CTRL_EXT); + EM_WRITE_REG(hw, E1000_CTRL_EXT, + ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA); + delay(300); + } + /* Read the PHY ID Registers to identify which PHY is onboard. */ for (hw->phy_addr = 1; (hw->phy_addr < 4); hw->phy_addr++) { ret_val = em_match_gig_phy(hw); @@ -6641,6 +6647,8 @@ em_read_mac_addr(struct em_hw *hw) if (hw->mac_type == em_icp_xxxx) { ia_base_addr = (uint16_t) EEPROM_IA_START_ICP_xxxx(hw->icp_xxxx_port_num); + } else if (hw->mac_type == em_82580) { + ia_base_addr = NVM_82580_LAN_FUNC_OFFSET(hw->bus_func); } for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) { offset = i >> 1; @@ -6660,7 +6668,6 @@ em_read_mac_addr(struct em_hw *hw) case em_82546_rev_3: case em_82571: case em_82575: - case em_82580: case em_80003es2lan: if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) hw->perm_mac_addr[5] ^= 0x01; @@ -8674,7 +8681,7 @@ STATIC int32_t em_get_phy_cfg_done(struct em_hw *hw) { int32_t timeout = PHY_CFG_TIMEOUT; - uint32_t cfg_mask = E1000_EEPROM_CFG_DONE; + uint32_t cfg_mask = E1000_NVM_CFG_DONE_PORT_0; DEBUGFUNC("em_get_phy_cfg_done"); switch (hw->mac_type) { @@ -8683,9 +8690,18 @@ em_get_phy_cfg_done(struct em_hw *hw) break; case em_80003es2lan: case em_82575: - /* 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; + case em_82580: + switch (hw->bus_func) { + case 1: + cfg_mask = E1000_NVM_CFG_DONE_PORT_1; + break; + case 2: + cfg_mask = E1000_NVM_CFG_DONE_PORT_2; + break; + case 3: + cfg_mask = E1000_NVM_CFG_DONE_PORT_3; + break; + } /* FALLTHROUGH */ case em_82571: case em_82572: diff --git a/sys/dev/pci/if_em_hw.h b/sys/dev/pci/if_em_hw.h index f745499bc31..bce466b9895 100644 --- a/sys/dev/pci/if_em_hw.h +++ b/sys/dev/pci/if_em_hw.h @@ -31,7 +31,7 @@ *******************************************************************************/ -/* $OpenBSD: if_em_hw.h,v 1.51 2011/05/02 12:25:42 jsg Exp $ */ +/* $OpenBSD: if_em_hw.h,v 1.52 2011/10/05 02:52:10 jsg Exp $ */ /* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */ /* if_em_hw.h @@ -949,6 +949,7 @@ struct em_ffvt_entry { #define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ #define E1000_FLA 0x0001C /* Flash Access - RW */ #define E1000_MDIC 0x00020 /* MDI Control - RW */ +#define E1000_MDICNFG 0x00E04 /* MDI Config - RW */ #define E1000_SCTL 0x00024 /* SerDes Control - RW */ #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ #define E1000_FEXTNVM 0x00028 /* Future Extended NVM register */ @@ -1543,6 +1544,8 @@ struct em_hw { boolean_t icp_xxxx_is_link_up; uint32_t icp_xxxx_port_num; struct gcu_softc * gcu; + uint8_t bus_func; + uint16_t swfw; }; #define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */ @@ -1590,6 +1593,7 @@ struct em_hw { #define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ #define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ #define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */ +#define E1000_CTRL_DEV_RST 0x20000000 /* Device Reset */ #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 */ @@ -1632,6 +1636,7 @@ struct em_hw { #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_DEV_RST_SET 0x00100000 #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 */ @@ -1750,6 +1755,7 @@ struct em_hw { #define E1000_MDIC_READY 0x10000000 #define E1000_MDIC_INT_EN 0x20000000 #define E1000_MDIC_ERROR 0x40000000 +#define E1000_MDIC_DEST 0x80000000 #define E1000_KUMCTRLSTA_MASK 0x0000FFFF #define E1000_KUMCTRLSTA_OFFSET 0x001F0000 @@ -1869,6 +1875,7 @@ struct em_hw { #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 */ +#define E1000_ICR_DRSTA 0x40000000 /* Device Reset Asserted */ /* Interrupt Cause Set */ #define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1898,6 +1905,7 @@ struct em_hw { #define E1000_ICS_DSW E1000_ICR_DSW #define E1000_ICS_PHYINT E1000_ICR_PHYINT #define E1000_ICS_EPRST E1000_ICR_EPRST +#define E1000_ICS_DRSTA E1000_ICR_DRSTA /* Interrupt Mask Set */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1927,6 +1935,7 @@ struct em_hw { #define E1000_IMS_DSW E1000_ICR_DSW #define E1000_IMS_PHYINT E1000_ICR_PHYINT #define E1000_IMS_EPRST E1000_ICR_EPRST +#define E1000_IMS_DRSTA E1000_ICR_DRSTA /* Interrupt Mask Clear */ #define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1956,6 +1965,7 @@ struct em_hw { #define E1000_IMC_DSW E1000_ICR_DSW #define E1000_IMC_PHYINT E1000_ICR_PHYINT #define E1000_IMC_EPRST E1000_ICR_EPRST +#define E1000_IMC_DRSTA E1000_ICR_DRSTA /* Receive Control */ #define E1000_RCTL_RST 0x00000001 /* Software reset */ @@ -2030,6 +2040,8 @@ struct em_hw { #define E1000_SWFW_PHY0_SM 0x0002 #define E1000_SWFW_PHY1_SM 0x0004 #define E1000_SWFW_MAC_CSR_SM 0x0008 +#define E1000_SWFW_PHY2_SM 0x0020 +#define E1000_SWFW_PHY3_SM 0x0040 /* Receive Descriptor */ #define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ @@ -2073,6 +2085,7 @@ struct em_hw { #define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */ #define E1000_RXDCTL_WTHRESH 0x003F0000 /* RXDCTL Writeback Threshold */ #define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */ +#define E1000_RXDCTL_QUEUE_ENABLE 0x2000000 /* Transmit Descriptor Control */ #define E1000_TXDCTL_PTHRESH 0x000000FF /* TXDCTL Prefetch Threshold */ @@ -2296,6 +2309,11 @@ struct em_host_command_info { #define E1000_MDALIGN 4096 +#define E1000_MDICNFG_EXT_MDIO 0x80000000 /* MDI ext/int destination */ +#define E1000_MDICNFG_COM_MDIO 0x40000000 /* MDI shared w/ lan 0 */ +#define E1000_MDICNFG_PHY_MASK 0x03E00000 +#define E1000_MDICNFG_PHY_SHIFT 21 + /* PCI-Ex registers*/ /* PCI-Ex Control Register */ @@ -2396,8 +2414,16 @@ struct em_host_command_info { #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 */ +#define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */ +#define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */ +#define E1000_NVM_CFG_DONE_PORT_2 0x100000 /* ...for third port */ +#define E1000_NVM_CFG_DONE_PORT_3 0x200000 /* ...for fourth port */ + +#define NVM_82580_LAN_FUNC_OFFSET(a) (a ? (0x40 + (0x40 * a)) : 0) + +/* Mask bits for fields in Word 0x24 of the NVM */ +#define NVM_WORD24_COM_MDIO 0x0008 /* MDIO interface shared */ +#define NVM_WORD24_EXT_MDIO 0x0004 /* MDIO accesses routed external */ /* Word definitions for ID LED Settings */ #define ID_LED_RESERVED_0000 0x0000 diff --git a/sys/dev/pci/if_em_osdep.h b/sys/dev/pci/if_em_osdep.h index 7d052145e03..bec2f2d5ed8 100644 --- a/sys/dev/pci/if_em_osdep.h +++ b/sys/dev/pci/if_em_osdep.h @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ -/* $OpenBSD: if_em_osdep.h,v 1.11 2011/07/26 14:57:57 deraadt Exp $ */ +/* $OpenBSD: if_em_osdep.h,v 1.12 2011/10/05 02:52:10 jsg Exp $ */ /* $FreeBSD: if_em_osdep.h,v 1.11 2003/05/02 21:17:08 pdeuskar Exp $ */ #ifndef _EM_OPENBSD_OS_H_ @@ -111,6 +111,17 @@ struct em_osdep ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg), \ value) +#define EM_READ_REG(hw, reg) \ + bus_space_read_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ + ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ + reg) + +#define EM_WRITE_REG(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, \ + reg, value) + + #define E1000_READ_REG_ARRAY(hw, reg, index) \ bus_space_read_4(((struct em_osdep *)(hw)->back)->mem_bus_space_tag, \ ((struct em_osdep *)(hw)->back)->mem_bus_space_handle, \ |