⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atl1_main.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<		  MAC_CTRL_SPEED_SHIFT);	/* flow control */	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);	/* PAD & CRC */	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);	/* preamble length */	value |= (((u32) adapter->hw.preamble_len		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);	/* vlan */	if (adapter->vlgrp)		value |= MAC_CTRL_RMV_VLAN;	/* rx checksum	   if (adapter->rx_csum)	   value |= MAC_CTRL_RX_CHKSUM_EN;	 */	/* filter mode */	value |= MAC_CTRL_BC_EN;	if (netdev->flags & IFF_PROMISC)		value |= MAC_CTRL_PROMIS_EN;	else if (netdev->flags & IFF_ALLMULTI)		value |= MAC_CTRL_MC_ALL_EN;	/* value |= MAC_CTRL_LOOPBACK; */	iowrite32(value, hw->hw_addr + REG_MAC_CTRL);}/* * atl1_set_mac - Change the Ethernet Address of the NIC * @netdev: network interface device structure * @p: pointer to an address structure * * Returns 0 on success, negative on failure */static int atl1_set_mac(struct net_device *netdev, void *p){	struct atl1_adapter *adapter = netdev_priv(netdev);	struct sockaddr *addr = p;	if (netif_running(netdev))		return -EBUSY;	if (!is_valid_ether_addr(addr->sa_data))		return -EADDRNOTAVAIL;	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);	atl1_set_mac_addr(&adapter->hw);	return 0;}static u32 atl1_check_link(struct atl1_adapter *adapter){	struct atl1_hw *hw = &adapter->hw;	struct net_device *netdev = adapter->netdev;	u32 ret_val;	u16 speed, duplex, phy_data;	int reconfig = 0;	/* MII_BMSR must read twice */	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);	if (!(phy_data & BMSR_LSTATUS)) {	/* link down */		if (netif_carrier_ok(netdev)) {	/* old link state: Up */			dev_info(&adapter->pdev->dev, "link is down\n");			adapter->link_speed = SPEED_0;			netif_carrier_off(netdev);			netif_stop_queue(netdev);		}		return ATL1_SUCCESS;	}	/* Link Up */	ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);	if (ret_val)		return ret_val;	switch (hw->media_type) {	case MEDIA_TYPE_1000M_FULL:		if (speed != SPEED_1000 || duplex != FULL_DUPLEX)			reconfig = 1;		break;	case MEDIA_TYPE_100M_FULL:		if (speed != SPEED_100 || duplex != FULL_DUPLEX)			reconfig = 1;		break;	case MEDIA_TYPE_100M_HALF:		if (speed != SPEED_100 || duplex != HALF_DUPLEX)			reconfig = 1;		break;	case MEDIA_TYPE_10M_FULL:		if (speed != SPEED_10 || duplex != FULL_DUPLEX)			reconfig = 1;		break;	case MEDIA_TYPE_10M_HALF:		if (speed != SPEED_10 || duplex != HALF_DUPLEX)			reconfig = 1;		break;	}	/* link result is our setting */	if (!reconfig) {		if (adapter->link_speed != speed		    || adapter->link_duplex != duplex) {			adapter->link_speed = speed;			adapter->link_duplex = duplex;			atl1_setup_mac_ctrl(adapter);			dev_info(&adapter->pdev->dev,				"%s link is up %d Mbps %s\n",				netdev->name, adapter->link_speed,				adapter->link_duplex == FULL_DUPLEX ?				"full duplex" : "half duplex");		}		if (!netif_carrier_ok(netdev)) {	/* Link down -> Up */			netif_carrier_on(netdev);			netif_wake_queue(netdev);		}		return ATL1_SUCCESS;	}	/* change orignal link status */	if (netif_carrier_ok(netdev)) {		adapter->link_speed = SPEED_0;		netif_carrier_off(netdev);		netif_stop_queue(netdev);	}	if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&	    hw->media_type != MEDIA_TYPE_1000M_FULL) {		switch (hw->media_type) {		case MEDIA_TYPE_100M_FULL:			phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |			           MII_CR_RESET;			break;		case MEDIA_TYPE_100M_HALF:			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;			break;		case MEDIA_TYPE_10M_FULL:			phy_data =			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;			break;		default:	/* MEDIA_TYPE_10M_HALF: */			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;			break;		}		atl1_write_phy_reg(hw, MII_BMCR, phy_data);		return ATL1_SUCCESS;	}	/* auto-neg, insert timer to re-config phy */	if (!adapter->phy_timer_pending) {		adapter->phy_timer_pending = true;		mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);	}	return ATL1_SUCCESS;}static void atl1_check_for_link(struct atl1_adapter *adapter){	struct net_device *netdev = adapter->netdev;	u16 phy_data = 0;	spin_lock(&adapter->lock);	adapter->phy_timer_pending = false;	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);	spin_unlock(&adapter->lock);	/* notify upper layer link down ASAP */	if (!(phy_data & BMSR_LSTATUS)) {	/* Link Down */		if (netif_carrier_ok(netdev)) {	/* old link state: Up */			dev_info(&adapter->pdev->dev, "%s link is down\n",				netdev->name);			adapter->link_speed = SPEED_0;			netif_carrier_off(netdev);			netif_stop_queue(netdev);		}	}	schedule_work(&adapter->link_chg_task);}/* * atl1_set_multi - Multicast and Promiscuous mode set * @netdev: network interface device structure * * The set_multi entry point is called whenever the multicast address * list or the network interface flags are updated.  This routine is * responsible for configuring the hardware for proper multicast, * promiscuous mode, and all-multi behavior. */static void atl1_set_multi(struct net_device *netdev){	struct atl1_adapter *adapter = netdev_priv(netdev);	struct atl1_hw *hw = &adapter->hw;	struct dev_mc_list *mc_ptr;	u32 rctl;	u32 hash_value;	/* Check for Promiscuous and All Multicast modes */	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);	if (netdev->flags & IFF_PROMISC)		rctl |= MAC_CTRL_PROMIS_EN;	else if (netdev->flags & IFF_ALLMULTI) {		rctl |= MAC_CTRL_MC_ALL_EN;		rctl &= ~MAC_CTRL_PROMIS_EN;	} else		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);	/* clear the old settings from the multicast hash table */	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));	/* compute mc addresses' hash value ,and put it into hash table */	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {		hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr);		atl1_hash_set(hw, hash_value);	}}/* * atl1_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure * @new_mtu: new value for maximum frame size * * Returns 0 on success, negative on failure */static int atl1_change_mtu(struct net_device *netdev, int new_mtu){	struct atl1_adapter *adapter = netdev_priv(netdev);	int old_mtu = netdev->mtu;	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {		dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");		return -EINVAL;	}	adapter->hw.max_frame_size = max_frame;	adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;	adapter->rx_buffer_len = (max_frame + 7) & ~7;	adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;	netdev->mtu = new_mtu;	if ((old_mtu != new_mtu) && netif_running(netdev)) {		atl1_down(adapter);		atl1_up(adapter);	}	return 0;}static void set_flow_ctrl_old(struct atl1_adapter *adapter){	u32 hi, lo, value;	/* RFD Flow Control */	value = adapter->rfd_ring.count;	hi = value / 16;	if (hi < 2)		hi = 2;	lo = value * 7 / 8;	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);	/* RRD Flow Control */	value = adapter->rrd_ring.count;	lo = value / 16;	hi = value * 7 / 8;	if (lo < 2)		lo = 2;	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);}static void set_flow_ctrl_new(struct atl1_hw *hw){	u32 hi, lo, value;	/* RXF Flow Control */	value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);	lo = value / 16;	if (lo < 192)		lo = 192;	hi = value * 7 / 8;	if (hi < lo)		hi = lo + 16;	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);	iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);	/* RRD Flow Control */	value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);	lo = value / 8;	hi = value * 7 / 8;	if (lo < 2)		lo = 2;	if (hi < lo)		hi = lo + 3;	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);	iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);}/* * atl1_configure - Configure Transmit&Receive Unit after Reset * @adapter: board private structure * * Configure the Tx /Rx unit of the MAC after a reset. */static u32 atl1_configure(struct atl1_adapter *adapter){	struct atl1_hw *hw = &adapter->hw;	u32 value;	/* clear interrupt status */	iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);	/* set MAC Address */	value = (((u32) hw->mac_addr[2]) << 24) |		(((u32) hw->mac_addr[3]) << 16) |		(((u32) hw->mac_addr[4]) << 8) |		(((u32) hw->mac_addr[5]));	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));	iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));	/* tx / rx ring */	/* HI base address */	iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),		hw->hw_addr + REG_DESC_BASE_ADDR_HI);	/* LO base address */	iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),		hw->hw_addr + REG_DESC_RFD_ADDR_LO);	iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),		hw->hw_addr + REG_DESC_RRD_ADDR_LO);	iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),		hw->hw_addr + REG_DESC_TPD_ADDR_LO);	iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),		hw->hw_addr + REG_DESC_CMB_ADDR_LO);	iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),		hw->hw_addr + REG_DESC_SMB_ADDR_LO);	/* element count */	value = adapter->rrd_ring.count;	value <<= 16;	value += adapter->rfd_ring.count;	iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);	iowrite32(adapter->tpd_ring.count, hw->hw_addr +		REG_DESC_TPD_RING_SIZE);	/* Load Ptr */	iowrite32(1, hw->hw_addr + REG_LOAD_PTR);	/* config Mailbox */	value = ((atomic_read(&adapter->tpd_ring.next_to_use)		  & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |		((atomic_read(&adapter->rrd_ring.next_to_clean)		& MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |		((atomic_read(&adapter->rfd_ring.next_to_use)		& MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);	iowrite32(value, hw->hw_addr + REG_MAILBOX);	/* config IPG/IFG */	value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)		 << MAC_IPG_IFG_IPGT_SHIFT) |		(((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)		<< MAC_IPG_IFG_MIFG_SHIFT) |		(((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)		<< MAC_IPG_IFG_IPGR1_SHIFT) |		(((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)		<< MAC_IPG_IFG_IPGR2_SHIFT);	iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);	/* config  Half-Duplex Control */	value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |		(((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)		<< MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |		MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |		(0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |		(((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)		<< MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);	iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);	/* set Interrupt Moderator Timer */	iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);	iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);	/* set Interrupt Clear Timer */	iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);	/* set max frame size hw will accept */	iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);	/* jumbo size & rrd retirement timer */	value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)		 << RXQ_JMBOSZ_TH_SHIFT) |		(((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)		<< RXQ_JMBO_LKAH_SHIFT) |		(((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)		<< RXQ_RRD_TIMER_SHIFT);	iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);	/* Flow Control */	switch (hw->dev_rev) {	case 0x8001:	case 0x9001:	case 0x9002:	case 0x9003:		set_flow_ctrl_old(adapter);		break;	default:		set_flow_ctrl_new(hw);		break;	}	/* config TXQ */	value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)		 << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |		(((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)		<< TXQ_CTRL_TXF_BURST_NUM_SHIFT) |		(((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)		<< TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |		TXQ_CTRL_EN;	iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);	/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */	value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)		<< TX_JUMBO_TASK_TH_SHIFT) |		(((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)		<< TX_TPD_MIN_IPG_SHIFT);	iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);	/* config RXQ */	value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)		<< RXQ_CTRL_RFD_BURST_NUM_SHIFT) |		(((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)		<< RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |		(((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)		<< RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |		RXQ_CTRL_EN;	iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);	/* config DMA Engine */	value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT) |		((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)		<< DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |		DMA_CTRL_DMAW_EN;	value |= (u32) hw->dma_ord;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -