FreeBSD/sys/dev/e1000/if_igb.c
/*********************************************************************
 *
 *  Set up an fresh starting state
 *
 **********************************************************************/
Set up an fresh starting state
Set up an fresh starting state
static void
igb_reset(struct adapter *adapter)
{
	device_t	dev = adapter->dev;
	struct e1000_hw *hw = &adapter->hw;
	struct e1000_fc_info *fc = &hw->fc;
	struct ifnet	*ifp = adapter->ifp;
	u32		pba = 0;
	u16		hwm;
	INIT_DEBUGOUT("igb_reset: begin");
	igb_get_hw_control(adapter);
	switch (hw->mac.type) {
	case e1000_82575:
		pba = E1000_PBA_32K;
		break;
	case e1000_82576:
	case e1000_vfadapt:
		pba = E1000_READ_REG(hw, E1000_RXPBS);
		pba &= E1000_RXPBS_SIZE_MASK_82576;
		break;
	case e1000_82580:
	case e1000_i350:
	case e1000_i354:
	case e1000_vfadapt_i350:
		pba = E1000_READ_REG(hw, E1000_RXPBS);
		pba = e1000_rxpbs_adjust_82580(pba);
		break;
	case e1000_i210:
	case e1000_i211:
		pba = E1000_PBA_34K;
	default:
		break;
	}
	if ((hw->mac.type == e1000_82575) && (ifp->if_mtu > ETHERMTU)) {
		u32 tx_space, min_tx, min_rx;
		pba = E1000_READ_REG(hw, E1000_PBA);
		tx_space = pba >> 16;
		pba &= 0xffff;
		min_tx = (adapter->max_frame_size +
		    sizeof(struct e1000_tx_desc) - ETHERNET_FCS_SIZE) * 2;
		min_tx = roundup2(min_tx, 1024);
		min_tx >>= 10;
                min_rx = adapter->max_frame_size;
                min_rx = roundup2(min_rx, 1024);
                min_rx >>= 10;
		if (tx_space < min_tx &&
		    ((min_tx - tx_space) < pba)) {
			pba = pba - (min_tx - tx_space);
                        if (pba < min_rx)
                                pba = min_rx;
		}
		E1000_WRITE_REG(hw, E1000_PBA, pba);
	}
	INIT_DEBUGOUT1("igb_init: pba=%dK",pba);
	hwm = min(((pba << 10) * 9 / 10),
	    ((pba << 10) - 2 * adapter->max_frame_size));
	if (hw->mac.type < e1000_82576) {
		fc->high_water = hwm & 0xFFF8;  
		fc->low_water = fc->high_water - 8;
	} else {
		fc->high_water = hwm & 0xFFF0;  
		fc->low_water = fc->high_water - 16;
	}
	fc->pause_time = IGB_FC_PAUSE_TIME;
	fc->send_xon = TRUE;
	if (adapter->fc)
		fc->requested_mode = adapter->fc;
	else
		fc->requested_mode = e1000_fc_default;
	e1000_reset_hw(hw);
	E1000_WRITE_REG(hw, E1000_WUC, 0);
	if (adapter->flags & IGB_MEDIA_RESET) {
		e1000_setup_init_funcs(hw, TRUE);
		e1000_get_bus_info(hw);
		adapter->flags &= ~IGB_MEDIA_RESET;
	}
	if (e1000_init_hw(hw) < 0)
		device_printf(dev, "Hardware Initialization Failed\n");
	igb_init_dmac(adapter, pba);
	E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN);
	e1000_get_phy_info(hw);
	e1000_check_for_link(hw);
	return;
}
static void igb_reset ( struct adapter * adapter ) { device_t dev = adapter -> dev ; struct e1000_hw * hw = & adapter -> hw ; struct e1000_fc_info * fc = & hw -> fc ; struct ifnet * ifp = adapter -> ifp ; u32 pba = 0 ; u16 hwm ; INIT_DEBUGOUT ( " " ) ; igb_get_hw_control ( adapter ) ; switch ( hw -> mac . type ) { case e1000_82575 : pba = E1000_PBA_32K ; break ; case e1000_82576 : case e1000_vfadapt : pba = E1000_READ_REG ( hw , E1000_RXPBS ) ; pba &= E1000_RXPBS_SIZE_MASK_82576 ; break ; case e1000_82580 : case e1000_i350 : case e1000_i354 : case e1000_vfadapt_i350 : pba = E1000_READ_REG ( hw , E1000_RXPBS ) ; pba = e1000_rxpbs_adjust_82580 ( pba ) ; break ; case e1000_i210 : case e1000_i211 : pba = E1000_PBA_34K ; default : break ; } if ( ( hw -> mac . type == e1000_82575 ) && ( ifp -> if_mtu > ETHERMTU ) ) { u32 tx_space , min_tx , min_rx ; pba = E1000_READ_REG ( hw , E1000_PBA ) ; tx_space = pba >> 16 ; pba &= 0xffff ; min_tx = ( adapter -> max_frame_size + sizeof ( struct e1000_tx_desc ) - ETHERNET_FCS_SIZE ) * 2 ; min_tx = roundup2 ( min_tx , 1024 ) ; min_tx >>= 10 ; min_rx = adapter -> max_frame_size ; min_rx = roundup2 ( min_rx , 1024 ) ; min_rx >>= 10 ; if ( tx_space < min_tx && ( ( min_tx - tx_space ) < pba ) ) { pba = pba - ( min_tx - tx_space ) ; if ( pba < min_rx ) pba = min_rx ; } E1000_WRITE_REG ( hw , E1000_PBA , pba ) ; } INIT_DEBUGOUT1 ( " " , pba ) ; hwm = min ( ( ( pba << 10 ) * 9 / 10 ) , ( ( pba << 10 ) - 2 * adapter -> max_frame_size ) ) ; if ( hw -> mac . type < e1000_82576 ) { fc -> high_water = hwm & 0xFFF8 ; fc -> low_water = fc -> high_water - 8 ; } else { fc -> high_water = hwm & 0xFFF0 ; fc -> low_water = fc -> high_water - 16 ; } fc -> pause_time = IGB_FC_PAUSE_TIME ; fc -> send_xon = TRUE ; if ( adapter -> fc ) fc -> requested_mode = adapter -> fc ; else fc -> requested_mode = e1000_fc_default ; e1000_reset_hw ( hw ) ; E1000_WRITE_REG ( hw , E1000_WUC , 0 ) ; if ( adapter -> flags & IGB_MEDIA_RESET ) { e1000_setup_init_funcs ( hw , TRUE ) ; e1000_get_bus_info ( hw ) ; adapter -> flags &= ~ IGB_MEDIA_RESET ; } if ( e1000_init_hw ( hw ) < 0 ) device_printf ( dev , " \n " ) ; igb_init_dmac ( adapter , pba ) ; E1000_WRITE_REG ( & adapter -> hw , E1000_VET , ETHERTYPE_VLAN ) ; e1000_get_phy_info ( hw ) ; e1000_check_for_link ( hw ) ; return ; }
Set up an fresh starting state
Set up an fresh starting state
/* Let the firmware know the OS is in control */ /*
	 * Packet Buffer Allocation (PBA)
	 * Writing PBA sets the receive portion of the buffer
	 * the remainder is used for the transmit buffer.
	 */ /* Special needs in case of Jumbo frames */ /*
                         * if short on rx space, rx wins
                         * and must trump tx adjustment
			 */ /*
	 * These parameters control the automatic generation (Tx) and
	 * response (Rx) to Ethernet PAUSE frames.
	 * - High water mark should allow for at least two frames to be
	 *   received after sending an XOFF.
	 * - Low water mark works best when it is very near the high water mark.
	 *   This allows the receiver to restart by sending XON when it has
	 *   drained a bit.
	 */ /* 8-byte granularity */ /* 16-byte granularity */ /* Issue a global reset */ /* Reset for AutoMediaDetect */ /* Setup DMA Coalescing */