/** * intelDown - quiesce the device and optionally reset the hardware * @adapter: board private structure * @reset: boolean flag to reset the hardware or not */ void IntelMausi::intelDown(struct e1000_adapter *adapter, bool reset) { struct e1000_hw *hw = &adapter->hw; UInt32 tctl, rctl; /* signal that we're down so the interrupt handler does not * reschedule our watchdog timer */ set_bit(__E1000_DOWN, &adapter->state); /* disable receives in the hardware */ rctl = intelReadMem32(E1000_RCTL); rctl &= ~E1000_RCTL_EN; intelWriteMem32(E1000_RCTL, rctl); /* flush and sleep below */ /* disable transmits in the hardware */ tctl = intelReadMem32(E1000_TCTL); tctl &= ~E1000_TCTL_EN; intelWriteMem32(E1000_TCTL, tctl); /* flush both disables and wait for them to finish */ intelFlush(); usleep_range(10000, 20000); intelDisableIRQ(); updateStatistics(adapter); clearDescriptors(); adapter->link_speed = 0; adapter->link_duplex = 0; /* Disable Si errata workaround on PCHx for jumbo frame flow */ if ((hw->mac.type >= e1000_pch2lan) && (mtu > ETH_DATA_LEN) && e1000_lv_jumbo_workaround_ich8lan(hw, false)) DebugLog("Ethernet [IntelMausi]: failed to disable jumbo frame workaround mode\n"); if (reset) intelReset(adapter); }
/** * intelConfigureTx - Configure Transmit Unit after Reset * @adapter: board private structure * * Configure the Tx unit of the MAC after a reset. **/ void IntelMausi::intelConfigureTx(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; UInt32 tctl, tarc; UInt32 txdctl; /* Setup the HW Tx Head and Tail descriptor pointers */ intelInitTxRing(); /* Set the Tx Interrupt Delay register */ intelWriteMem32(E1000_TIDV, adapter->tx_int_delay); /* Tx irq moderation */ intelWriteMem32(E1000_TADV, adapter->tx_abs_int_delay); txdctl = intelReadMem32(E1000_TXDCTL(0)); /* Fix TXDCTL for 82579, I217 and I218. */ if ((chipType == board_pch_lpt) || (chipType == board_pch2lan)) { txdctl = 0x01410101; intelWriteMem32(E1000_TXDCTL(0), txdctl); } /* erratum work around: set txdctl the same for both queues */ intelWriteMem32(E1000_TXDCTL(1), txdctl); /* Program the Transmit Control Register */ tctl = intelReadMem32(E1000_TCTL); tctl &= ~E1000_TCTL_CT; tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); /* errata: program both queues to unweighted RR */ if (adapter->flags & FLAG_TARC_SET_BIT_ZERO) { tarc = intelReadMem32(E1000_TARC(0)); tarc |= 1; intelWriteMem32(E1000_TARC(0), tarc); tarc = intelReadMem32(E1000_TARC(1)); tarc |= 1; intelWriteMem32(E1000_TARC(1), tarc); } intelWriteMem32(E1000_TCTL, tctl); hw->mac.ops.config_collision_dist(hw); }
void IntelMausi::intelSetupRxControl(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 rctl, rfctl; /* Workaround Si errata on PCHx - configure jumbo frame flow. * If jumbo frames not set, program related MAC/PHY registers * to h/w defaults */ if (hw->mac.type >= e1000_pch2lan) { s32 ret_val; if (mtu > ETH_DATA_LEN) ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); else ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); if (ret_val) DebugLog("Ethernet [IntelMausi]: failed to enable/disable jumbo frame workaround mode.\n"); } /* Program MC offset vector base */ rctl = intelReadMem32(E1000_RCTL); rctl &= ~(3 << E1000_RCTL_MO_SHIFT); rctl |= E1000_RCTL_BAM | E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); /* Do not Store bad packets */ rctl &= ~E1000_RCTL_SBP; /* Enable Long Packet receive */ if (mtu <= ETH_DATA_LEN) rctl &= ~E1000_RCTL_LPE; else rctl |= E1000_RCTL_LPE; /* Some systems expect that the CRC is included in SMBUS traffic. The * hardware strips the CRC before sending to both SMBUS (BMC) and to * host memory when this is enabled */ if (adapter->flags2 & FLAG2_CRC_STRIPPING) rctl |= E1000_RCTL_SECRC; /* Workaround Si errata on 82577 PHY - configure IPG for jumbos */ if ((hw->phy.type == e1000_phy_82577) && (rctl & E1000_RCTL_LPE)) { u16 phy_data; e1e_rphy(hw, PHY_REG(770, 26), &phy_data); phy_data &= 0xfff8; phy_data |= (1 << 2); e1e_wphy(hw, PHY_REG(770, 26), phy_data); e1e_rphy(hw, 22, &phy_data); phy_data &= 0x0fff; phy_data |= (1 << 14); e1e_wphy(hw, 0x10, 0x2823); e1e_wphy(hw, 0x11, 0x0003); e1e_wphy(hw, 22, phy_data); } /* Set buffer sizes to 2048 */ //rctl |= (0x2 << E1000_RCTL_FLXB_SHIFT); rctl &= ~(E1000_RCTL_SZ_256 | E1000_RCTL_BSEX); /* Enable Extended Status in all Receive Descriptors */ rfctl = intelReadMem32(E1000_RFCTL); rfctl |= (E1000_RFCTL_NEW_IPV6_EXT_DIS | E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_EXTEN | E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS); intelWriteMem32(E1000_RFCTL, rfctl); intelWriteMem32(E1000_RCTL, rctl); }
void IntelMausi::intelDisable() { struct e1000_hw *hw = &adapterData.hw; UInt32 wufc = adapterData.wol; UInt32 ctrl, ctrlExt, rctl, status; /* Flush LPIC. */ intelFlushLPIC(); status = intelReadMem32(E1000_STATUS); if (status & E1000_STATUS_LU) wufc &= ~E1000_WUFC_LNKC; if (wolActive && wufc) { intelDown(&adapterData, false); intelSetupRxControl(&adapterData); rctl = intelReadMem32(E1000_RCTL); rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); /* turn on all-multi mode if wake on multicast is enabled */ if (wufc & E1000_WUFC_MC) rctl |= E1000_RCTL_MPE; intelWriteMem32(E1000_RCTL, rctl); ctrl = intelReadMem32(E1000_CTRL); ctrl |= E1000_CTRL_ADVD3WUC; if (!(adapterData.flags2 & FLAG2_HAS_PHY_WAKEUP)) ctrl |= E1000_CTRL_EN_PHY_PWR_MGMT; intelWriteMem32(E1000_CTRL, ctrl); if (adapterData.hw.phy.media_type == e1000_media_type_fiber || adapterData.hw.phy.media_type == e1000_media_type_internal_serdes) { /* keep the laser running in D3 */ ctrlExt = intelReadMem32(E1000_CTRL_EXT); ctrlExt |= E1000_CTRL_EXT_SDP3_DATA; intelWriteMem32(E1000_CTRL_EXT, ctrlExt); } if (adapterData.flags & FLAG_IS_ICH) e1000_suspend_workarounds_ich8lan(hw); if (adapterData.flags2 & FLAG2_HAS_PHY_WAKEUP) { /* enable wakeup by the PHY */ intelInitPhyWakeup(wufc); } else { /* enable wakeup by the MAC */ intelWriteMem32(E1000_WUFC, wufc); intelWriteMem32(E1000_WUC, E1000_WUC_PME_EN); } DebugLog("Ethernet [IntelMausi]: WUFC=0x%08x.\n", wufc); } else { intelDown(&adapterData, true); intelWriteMem32(E1000_WUC, 0); intelWriteMem32(E1000_WUFC, 0); intelPowerDownPhy(&adapterData); } /* If AMT is enabled, let the firmware know that the network * interface is now closed */ if (adapterData.flags & FLAG_HAS_AMT) e1000e_release_hw_control(&adapterData); }
void IntelMausi::intelDisableIRQ() { intelWriteMem32(E1000_IMC, 0xFFFFFFFF); intelFlush(); }
void IntelMausi::intelEnableIRQ(UInt32 newMask) { intelWriteMem32(E1000_IMS, newMask); intelFlush(); }