/**
 * 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();
}