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

📄 e1000_main.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
/** * e1000_intr - Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure * @pt_regs: CPU registers structure **/static voide1000_intr(int irq, void *data, struct pt_regs *regs){	struct net_device *netdev = data;	struct e1000_adapter *adapter = netdev->priv;	uint32_t icr = E1000_READ_REG(&adapter->hw, ICR);	int i;	if(!icr)		return;  /* Not our interrupt */	if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {		adapter->hw.get_link_status = 1;		mod_timer(&adapter->watchdog_timer, jiffies);	}	for(i = 0; i < E1000_MAX_INTR; i++)		if(!e1000_clean_rx_irq(adapter) &&		   !e1000_clean_tx_irq(adapter))			break;}/** * e1000_clean_tx_irq - Reclaim resources after transmit completes * @adapter: board private structure **/static boolean_te1000_clean_tx_irq(struct e1000_adapter *adapter){	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;	struct net_device *netdev = adapter->netdev;	struct pci_dev *pdev = adapter->pdev;	struct e1000_tx_desc *tx_desc;	int i, cleaned = FALSE;	i = tx_ring->next_to_clean;	tx_desc = E1000_TX_DESC(*tx_ring, i);	while(tx_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {		cleaned = TRUE;		if(tx_ring->buffer_info[i].dma) {			pci_unmap_page(pdev,			               tx_ring->buffer_info[i].dma,			               tx_ring->buffer_info[i].length,			               PCI_DMA_TODEVICE);			tx_ring->buffer_info[i].dma = 0;		}		if(tx_ring->buffer_info[i].skb) {			dev_kfree_skb_any(tx_ring->buffer_info[i].skb);			tx_ring->buffer_info[i].skb = NULL;		}		tx_desc->buffer_addr = 0;		tx_desc->lower.data = 0;		tx_desc->upper.data = 0;		if(++i == tx_ring->count) i = 0;		tx_desc = E1000_TX_DESC(*tx_ring, i);	}	tx_ring->next_to_clean = i;	if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev))		netif_wake_queue(netdev);	return cleaned;}/** * e1000_clean_rx_irq - Send received data up the network stack, * @adapter: board private structure **/static boolean_te1000_clean_rx_irq(struct e1000_adapter *adapter){	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;	struct net_device *netdev = adapter->netdev;	struct pci_dev *pdev = adapter->pdev;	struct e1000_rx_desc *rx_desc;	struct sk_buff *skb;	unsigned long flags;	uint32_t length;	uint8_t last_byte;	int i, cleaned = FALSE;	i = rx_ring->next_to_clean;	rx_desc = E1000_RX_DESC(*rx_ring, i);	while(rx_desc->status & E1000_RXD_STAT_DD) {		cleaned = TRUE;		pci_unmap_single(pdev,		                 rx_ring->buffer_info[i].dma,		                 rx_ring->buffer_info[i].length,		                 PCI_DMA_FROMDEVICE);		skb = rx_ring->buffer_info[i].skb;		length = le16_to_cpu(rx_desc->length);		if(!(rx_desc->status & E1000_RXD_STAT_EOP)) {			/* All receives must fit into a single buffer */			E1000_DBG("Receive packet consumed multiple buffers\n");			dev_kfree_skb_irq(skb);			rx_desc->status = 0;			rx_ring->buffer_info[i].skb = NULL;			if(++i == rx_ring->count) i = 0;			rx_desc = E1000_RX_DESC(*rx_ring, i);			continue;		}		if(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) {			last_byte = *(skb->data + length - 1);			if(TBI_ACCEPT(&adapter->hw, rx_desc->status,			              rx_desc->errors, length, last_byte)) {				spin_lock_irqsave(&adapter->stats_lock, flags);				e1000_tbi_adjust_stats(&adapter->hw,				                       &adapter->stats,				                       length, skb->data);				spin_unlock_irqrestore(&adapter->stats_lock,				                       flags);				length--;			} else {				dev_kfree_skb_irq(skb);				rx_desc->status = 0;				rx_ring->buffer_info[i].skb = NULL;				if(++i == rx_ring->count) i = 0;				rx_desc = E1000_RX_DESC(*rx_ring, i);				continue;			}		}		/* Good Receive */		skb_put(skb, length - ETHERNET_FCS_SIZE);		/* Receive Checksum Offload */		e1000_rx_checksum(adapter, rx_desc, skb);		skb->protocol = eth_type_trans(skb, netdev);		if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {			vlan_hwaccel_rx(skb, adapter->vlgrp,				(rx_desc->special & E1000_RXD_SPC_VLAN_MASK));		} else {			netif_rx(skb);		}		netdev->last_rx = jiffies;		rx_desc->status = 0;		rx_ring->buffer_info[i].skb = NULL;		if(++i == rx_ring->count) i = 0;		rx_desc = E1000_RX_DESC(*rx_ring, i);	}	rx_ring->next_to_clean = i;	e1000_alloc_rx_buffers(adapter);	return cleaned;}/** * e1000_alloc_rx_buffers - Replace used receive buffers * @data: address of board private structure **/static voide1000_alloc_rx_buffers(struct e1000_adapter *adapter){	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;	struct net_device *netdev = adapter->netdev;	struct pci_dev *pdev = adapter->pdev;	struct e1000_rx_desc *rx_desc;	struct sk_buff *skb;	int reserve_len = 2;	int i;	i = rx_ring->next_to_use;	while(!rx_ring->buffer_info[i].skb) {		rx_desc = E1000_RX_DESC(*rx_ring, i);		skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len);		if(!skb) {			/* Better luck next round */			break;		}		/* Make buffer alignment 2 beyond a 16 byte boundary		 * this will result in a 16 byte aligned IP header after		 * the 14 byte MAC header is removed		 */		skb_reserve(skb, reserve_len);		skb->dev = netdev;		rx_ring->buffer_info[i].skb = skb;		rx_ring->buffer_info[i].length = adapter->rx_buffer_len;		rx_ring->buffer_info[i].dma =			pci_map_single(pdev,			               skb->data,			               adapter->rx_buffer_len,			               PCI_DMA_FROMDEVICE);		rx_desc->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma);		if((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i) {			/* Force memory writes to complete before letting h/w			 * know there are new descriptors to fetch.  (Only			 * applicable for weak-ordered memory model archs,			 * such as IA-64). */			wmb();			E1000_WRITE_REG(&adapter->hw, RDT, i);		}		if(++i == rx_ring->count) i = 0;	}	rx_ring->next_to_use = i;}/** * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers. * @adapter: **/static voide1000_smartspeed(struct e1000_adapter *adapter){	uint16_t phy_status;	uint16_t phy_ctrl;	if((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||	   !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL))		return;	if(adapter->smartspeed == 0) {		/* If Master/Slave config fault is asserted twice,		 * we assume back-to-back */		e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);		if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;		e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);		if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;		e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);		if(phy_ctrl & CR_1000T_MS_ENABLE) {			phy_ctrl &= ~CR_1000T_MS_ENABLE;			e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL,					    phy_ctrl);			adapter->smartspeed++;			if(!e1000_phy_setup_autoneg(&adapter->hw) &&			   !e1000_read_phy_reg(&adapter->hw, PHY_CTRL,				   	       &phy_ctrl)) {				phy_ctrl |= (MII_CR_AUTO_NEG_EN |					     MII_CR_RESTART_AUTO_NEG);				e1000_write_phy_reg(&adapter->hw, PHY_CTRL,						    phy_ctrl);			}		}		return;	} else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {		/* If still no link, perhaps using 2/3 pair cable */		e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);		phy_ctrl |= CR_1000T_MS_ENABLE;		e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl);		if(!e1000_phy_setup_autoneg(&adapter->hw) &&		   !e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) {			phy_ctrl |= (MII_CR_AUTO_NEG_EN |				     MII_CR_RESTART_AUTO_NEG);			e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl);		}	}	/* Restart process after E1000_SMARTSPEED_MAX iterations */	if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX)		adapter->smartspeed = 0;}/** * e1000_ioctl - * @netdev: * @ifreq: * @cmd: **/static inte1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd){	switch (cmd) {	case SIOCGMIIPHY:	case SIOCGMIIREG:	case SIOCSMIIREG:		return e1000_mii_ioctl(netdev, ifr, cmd);	case SIOCETHTOOL:		return e1000_ethtool_ioctl(netdev, ifr);	default:		return -EOPNOTSUPP;	}}/** * e1000_mii_ioctl - * @netdev: * @ifreq: * @cmd: **/static inte1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd){	struct e1000_adapter *adapter = netdev->priv;	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;	int retval;	uint16_t mii_reg;	uint16_t spddplx;	if(adapter->hw.media_type == e1000_media_type_fiber)		return -EOPNOTSUPP;	switch (cmd) {	case SIOCGMIIPHY:		data->phy_id = adapter->hw.phy_addr;		break;	case SIOCGMIIREG:		if (!capable(CAP_NET_ADMIN))			return -EPERM;		if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,				   &data->val_out))			return -EIO;		break;	case SIOCSMIIREG:		if (!capable(CAP_NET_ADMIN))			return -EPERM;		if (data->reg_num & ~(0x1F))			return -EFAULT;		mii_reg = data->val_in;		if (e1000_write_phy_reg(&adapter->hw, data->reg_num,					data->val_in))			return -EIO;		if (adapter->hw.phy_type == e1000_phy_m88) {			switch (data->reg_num) {			case PHY_CTRL:				if(data->val_in & MII_CR_AUTO_NEG_EN) {					adapter->hw.autoneg = 1;					adapter->hw.autoneg_advertised = 0x2F;				} else {					if (data->val_in & 0x40)						spddplx = SPEED_1000;					else if (data->val_in & 0x2000)						spddplx = SPEED_100;					else						spddplx = SPEED_10;					spddplx += (data->val_in & 0x100)						   ? FULL_DUPLEX :						   HALF_DUPLEX;					retval = e1000_set_spd_dplx(adapter,								    spddplx);					if(retval)						return retval;				}				if(netif_running(adapter->netdev)) {					e1000_down(adapter);					e1000_up(adapter);				} else					e1000_reset(adapter);				break;			case M88E1000_PHY_SPEC_CTRL:			case M88E1000_EXT_PHY_SPEC_CTRL:				if (e1000_phy_reset(&adapter->hw))					return -EIO;				break;			}		}		break;	default:		return -EOPNOTSUPP;	}	return E1000_SUCCESS;}/** * e1000_rx_checksum - Receive Checksum Offload for 82543 * @adapter: board private structure * @rx_desc: receive descriptor * @sk_buff: socket buffer with received data **/static inline voide1000_rx_checksum(struct e1000_adapter *adapter,                  struct e1000_rx_desc *rx_desc,                  struct sk_buff *skb){	/* 82543 or newer only */	if((adapter->hw.mac_type < e1000_82543) ||	/* Ignore Checksum bit is set */	(rx_desc->status & E1000_RXD_STAT_IXSM) ||	/* TCP Checksum has not been calculated */	(!(rx_desc->status & E1000_RXD_STAT_TCPCS))) {		skb->ip_summed = CHECKSUM_NONE;		return;	}	/* At this point we know the hardware did the TCP checksum */	/* now look at the TCP checksum error bit */	if(rx_desc->errors & E1000_RXD_ERR_TCPE) {		/* let the stack verify checksum errors */		skb->ip_summed = CHECKSUM_NONE;		adapter->hw_csum_err++;	} else {	/* TCP checksum is good */		skb->ip_summed = CHECKSUM_UNNECESSARY;		adapter->hw_csum_good++;	}}voide1000_pci_set_mwi(struct e1000_hw *hw){	struct e1000_adapter *adapter = hw->back;	pci_set_mwi(adapter->pdev);}voide1000_pci_clear_mwi(struct e1000_hw *hw){	struct e1000_adapter *adapter = hw->back;	pci_clear_mwi(adapter->pdev);}voide1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value){	struct e1000_adapter *adapter = hw->back;	pci_read_config_word(adapter->pdev, reg, value);}voide1000_write_pci_cfg(struct 

⌨️ 快捷键说明

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