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

📄 ethtool.c

📁 DELL755 Intel 网卡驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
		 * the cause register and then force the same		 * interrupt and see if one gets posted.  If		 * an interrupt was not posted to the bus, the		 * test failed.		 */		adapter->test_icr = 0;		ew32(IMS, mask);		ew32(ICS, mask);		msleep(10);		if (!(adapter->test_icr & mask)) {			*data = 4;			break;		}		if (!shared_int) {			/*			 * Disable the other interrupts to be reported in			 * the cause register and then force the other			 * interrupts and see if any get posted.  If			 * an interrupt was posted to the bus, the			 * test failed.			 */			adapter->test_icr = 0;			ew32(IMC, ~mask & 0x00007FFF);			ew32(ICS, ~mask & 0x00007FFF);			msleep(10);			if (adapter->test_icr) {				*data = 5;				break;			}		}	}	/* Disable all the interrupts */	ew32(IMC, 0xFFFFFFFF);	msleep(10);	/* Unhook test interrupt handler */	free_irq(irq, netdev);#ifdef CONFIG_E1000E_MSIXout:	if (int_mode == E1000E_INT_MODE_MSIX) {		e1000_reset_interrupt_capability(adapter);		adapter->int_mode = int_mode;		e1000_set_interrupt_capability(adapter);	}	return ret_val;#else	return *data;#endif}static void e1000_free_desc_rings(struct e1000_adapter *adapter){	struct e1000_ring *tx_ring = &adapter->test_tx_ring;	struct e1000_ring *rx_ring = &adapter->test_rx_ring;	struct pci_dev *pdev = adapter->pdev;	int i;	if (tx_ring->desc && tx_ring->buffer_info) {		for (i = 0; i < tx_ring->count; i++) {			if (tx_ring->buffer_info[i].dma)				pci_unmap_single(pdev,					tx_ring->buffer_info[i].dma,					tx_ring->buffer_info[i].length,					PCI_DMA_TODEVICE);			if (tx_ring->buffer_info[i].skb)				dev_kfree_skb(tx_ring->buffer_info[i].skb);		}	}	if (rx_ring->desc && rx_ring->buffer_info) {		for (i = 0; i < rx_ring->count; i++) {			if (rx_ring->buffer_info[i].dma)				pci_unmap_single(pdev,					rx_ring->buffer_info[i].dma,					2048, PCI_DMA_FROMDEVICE);			if (rx_ring->buffer_info[i].skb)				dev_kfree_skb(rx_ring->buffer_info[i].skb);		}	}	if (tx_ring->desc) {		dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,				  tx_ring->dma);		tx_ring->desc = NULL;	}	if (rx_ring->desc) {		dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,				  rx_ring->dma);		rx_ring->desc = NULL;	}	kfree(tx_ring->buffer_info);	tx_ring->buffer_info = NULL;	kfree(rx_ring->buffer_info);	rx_ring->buffer_info = NULL;}static int e1000_setup_desc_rings(struct e1000_adapter *adapter){	struct e1000_ring *tx_ring = &adapter->test_tx_ring;	struct e1000_ring *rx_ring = &adapter->test_rx_ring;	struct pci_dev *pdev = adapter->pdev;	struct e1000_hw *hw = &adapter->hw;	u32 rctl;	int i;	int ret_val;	/* Setup Tx descriptor ring and Tx buffers */	if (!tx_ring->count)		tx_ring->count = E1000_DEFAULT_TXD;	if (!(tx_ring->buffer_info = kcalloc(tx_ring->count,	                                     sizeof(struct e1000_buffer),	                                     GFP_KERNEL))) {		ret_val = 1;		goto err_nomem;	}	tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc);	tx_ring->size = ALIGN(tx_ring->size, 4096);	tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,					   &tx_ring->dma, GFP_KERNEL);	if (!tx_ring->desc) {		ret_val = 2;		goto err_nomem;	}	tx_ring->next_to_use = 0;	tx_ring->next_to_clean = 0;	ew32(TDBAL(0), ((u64) tx_ring->dma & 0x00000000FFFFFFFF));	ew32(TDBAH(0), ((u64) tx_ring->dma >> 32));	ew32(TDLEN(0), tx_ring->count * sizeof(struct e1000_tx_desc));	ew32(TDH(0), 0);	ew32(TDT(0), 0);	ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR |	     E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |	     E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT);	for (i = 0; i < tx_ring->count; i++) {		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i);		struct sk_buff *skb;		unsigned int skb_size = 1024;		skb = alloc_skb(skb_size, GFP_KERNEL);		if (!skb) {			ret_val = 3;			goto err_nomem;		}		skb_put(skb, skb_size);		tx_ring->buffer_info[i].skb = skb;		tx_ring->buffer_info[i].length = skb->len;		tx_ring->buffer_info[i].dma =			pci_map_single(pdev, skb->data, skb->len,				       PCI_DMA_TODEVICE);		if (pci_dma_mapping_error(tx_ring->buffer_info[i].dma)) {			ret_val = 4;			goto err_nomem;		}		tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma);		tx_desc->lower.data = cpu_to_le32(skb->len);		tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP |						   E1000_TXD_CMD_IFCS |						   E1000_TXD_CMD_RS);		tx_desc->upper.data = 0;	}	/* Setup Rx descriptor ring and Rx buffers */	if (!rx_ring->count)		rx_ring->count = E1000_DEFAULT_RXD;	if (!(rx_ring->buffer_info = kcalloc(rx_ring->count,	                                     sizeof(struct e1000_buffer),	                                     GFP_KERNEL))) {		ret_val = 5;		goto err_nomem;	}	rx_ring->size = rx_ring->count * sizeof(struct e1000_rx_desc);	rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,					   &rx_ring->dma, GFP_KERNEL);	if (!rx_ring->desc) {		ret_val = 6;		goto err_nomem;	}	rx_ring->next_to_use = 0;	rx_ring->next_to_clean = 0;	rctl = er32(RCTL);	ew32(RCTL, rctl & ~E1000_RCTL_EN);	ew32(RDBAL(0), ((u64) rx_ring->dma & 0xFFFFFFFF));	ew32(RDBAH(0), ((u64) rx_ring->dma >> 32));	ew32(RDLEN(0), rx_ring->size);	ew32(RDH(0), 0);	ew32(RDT(0), 0);	rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |		E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE |		E1000_RCTL_SBP | E1000_RCTL_SECRC |		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |		(adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);	ew32(RCTL, rctl);	for (i = 0; i < rx_ring->count; i++) {		struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i);		struct sk_buff *skb;		skb = alloc_skb(2048 + NET_IP_ALIGN, GFP_KERNEL);		if (!skb) {			ret_val = 7;			goto err_nomem;		}		skb_reserve(skb, NET_IP_ALIGN);		rx_ring->buffer_info[i].skb = skb;		rx_ring->buffer_info[i].dma =			pci_map_single(pdev, skb->data, 2048,				       PCI_DMA_FROMDEVICE);		if (pci_dma_mapping_error(rx_ring->buffer_info[i].dma)) {			ret_val = 8;			goto err_nomem;		}		rx_desc->buffer_addr =			cpu_to_le64(rx_ring->buffer_info[i].dma);		memset(skb->data, 0x00, skb->len);	}	return 0;err_nomem:	e1000_free_desc_rings(adapter);	return ret_val;}static void e1000_phy_disable_receiver(struct e1000_adapter *adapter){	/* Write out to PHY registers 29 and 30 to disable the Receiver. */	adapter->hw.phy.ops.write_reg(&adapter->hw, 29, 0x001F);	adapter->hw.phy.ops.write_reg(&adapter->hw, 30, 0x8FFC);	adapter->hw.phy.ops.write_reg(&adapter->hw, 29, 0x001A);	adapter->hw.phy.ops.write_reg(&adapter->hw, 30, 0x8FF0);}static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter){	struct e1000_hw *hw = &adapter->hw;	u32 ctrl_reg = 0;	u32 stat_reg = 0;	u16 phy_reg = 0;	hw->mac.autoneg = 0;	if (hw->phy.type == e1000_phy_m88) {		/* Auto-MDI/MDIX Off */		hw->phy.ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);		/* reset to update Auto-MDI/MDIX */		hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x9140);		/* autoneg off */		hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x8140);	} else if (hw->phy.type == e1000_phy_gg82563)		hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC);	ctrl_reg = er32(CTRL);	switch (hw->phy.type) {	case e1000_phy_ife:		/* force 100, set loopback */		hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x6100);		/* Now set up the MAC to the same speed/duplex as the PHY. */		ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */		ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */			     E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */			     E1000_CTRL_SPD_100 |/* Force Speed to 100 */			     E1000_CTRL_FD);	 /* Force Duplex to FULL */		break;	case e1000_phy_bm:		/* Set Default MAC Interface speed to 1GB */		hw->phy.ops.read_reg(hw, PHY_REG(2, 21), &phy_reg);		phy_reg &= ~0x0007;		phy_reg |= 0x006;		hw->phy.ops.write_reg(hw, PHY_REG(2, 21), phy_reg);		/* Assert SW reset for above settings to take effect */		hw->phy.ops.commit(hw);		mdelay(1);		/* Force Full Duplex */		hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &phy_reg);		hw->phy.ops.write_reg(hw, PHY_REG(769, 16), phy_reg | 0x000C);		/* Set Link Up (in force link) */		hw->phy.ops.read_reg(hw, PHY_REG(776, 16), &phy_reg);		hw->phy.ops.write_reg(hw, PHY_REG(776, 16), phy_reg | 0x0040);		/* Force Link */		hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &phy_reg);		hw->phy.ops.write_reg(hw, PHY_REG(769, 16), phy_reg | 0x0040);		/* Set Early Link Enable */		hw->phy.ops.read_reg(hw, PHY_REG(769, 20), &phy_reg);		hw->phy.ops.write_reg(hw, PHY_REG(769, 20), phy_reg | 0x0400);		/* fall through */	default:		/* force 1000, set loopback */		hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x4140);		mdelay(250);		/* Now set up the MAC to the same speed/duplex as the PHY. */		ctrl_reg = er32(CTRL);		ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */		ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */			     E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */			     E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */			     E1000_CTRL_FD);	 /* Force Duplex to FULL */		if (adapter->flags & FLAG_IS_ICH)			ctrl_reg |= E1000_CTRL_SLU;	/* Set Link Up */	}	if (hw->phy.media_type == e1000_media_type_copper &&	    hw->phy.type == e1000_phy_m88) {		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */	} else {		/*		 * Set the ILOS bit on the fiber Nic if half duplex link is		 * detected.		 */		stat_reg = er32(STATUS);		if ((stat_reg & E1000_STATUS_FD) == 0)			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);	}	ew32(CTRL, ctrl_reg);	/*	 * Disable the receiver on the PHY so when a cable is plugged in, the	 * PHY does not begin to autoneg when a cable is reconnected to the NIC.	 */	if (hw->phy.type == e1000_phy_m88)		e1000_phy_disable_receiver(adapter);	udelay(500);	return 0;}static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter){	struct e1000_hw *hw = &adapter->hw;	u32 ctrl = er32(CTRL);	int link = 0;	/* special requirements for 82571/82572 fiber adapters */	/*	 * jump through hoops to make sure link is up because serdes	 * link is hardwired up	 */	ctrl |= E1000_CTRL_SLU;	ew32(CTRL, ctrl);	/* disable autoneg */	ctrl = er32(TXCW);	ctrl &= ~(1 << 31);	ew32(TXCW, ctrl);	link = (er32(STATUS) & E1000_STATUS_LU);	if (!link) {		/* set invert loss of signal */		ctrl = er32(CTRL);		ctrl |= E1000_CTRL_ILOS;		ew32(CTRL, ctrl);	}	/*	 * special write to serdes control register to enable SerDes analog	 * loopback	 */#define E1000_SERDES_LB_ON 0x410	ew32(SCTL, E1000_SERDES_LB_ON);	msleep(10);	return 0;}/* only call this for fiber/serdes connections to es2lan */static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter){	struct e1000_hw *hw = &adapter->hw;	u32 ctrlext = er32(CTRL_EXT);	u32 ctrl = er32(CTRL);	/*	 * save CTRL_EXT to restore later, reuse an empty variable (unused	 * on mac_type 80003es2lan)	 */	adapter->tx_fifo_head = ctrlext;	/* clear the serdes mode bits, putting the device into mac loopback */	ctrlext &= ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;	ew32(CTRL_EXT, ctrlext);	/* force speed to 1000/FD, link up */	ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);	ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX |		 E1000_CTRL_SPD_1000 | E1000_CTRL_FD);	ew32(CTRL, ctrl);	/* set mac loopback */	ctrl = er32(RCTL);	ctrl |= E1000_RCTL_LBM_MAC;	ew32(RCTL, ctrl);	/* set testing mode parameters (no need to reset later) */#define KMRNCTRLSTA_OPMODE (0x1F << 16)#define KMRNCTRLSTA_OPMODE_1GB_FD_GMII 0x0582	ew32(KMRNCTRLSTA,	     (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII));	return 0;}static int e1000_setup_loopback_test(struct e1000_adapter *adapter){	struct e1000_hw *hw = &adapter->hw;	u32 rctl;	if (hw->phy.media_type == e1000_media_type_fiber ||	    hw->phy.media_type == e1000_media_type_internal_serdes) {		switch (hw->mac.type) {		case e1000_80003es2lan:			return e1000_set_es2lan_mac_loopback(adapter);			break;		case e1000_82571:		case e1000_82572:			return e1000_set_82571_fiber_loopback(adapter);			break;		default:			rctl = er32(RCTL);			rctl |= E1000_RCTL_LBM_TCVR;			ew32(RCTL, rctl);			return 0;		}	} else if (hw->phy.media_type == e1000_media_type_copper) {		return e1000_integrated_phy_loopback(adapter);	}	return 7;}static void e1000_loopback_cleanup(struct e1000_adapter *adapter){	struct e1000_hw *hw = &adapter->hw;	u32 rctl;	u16 phy_reg;	rctl = er32(RCTL);	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);	ew32(RCTL, rctl);	switch (hw->mac.type) {	case e1000_80003es2lan:		if (hw->phy.media_type == e1000_media_type_fiber ||		    hw->phy.media_type == e1000_media_type_internal_serdes) {			/* restore CTRL_EXT, stealing space from tx_fifo_head */			ew32(CTRL_EXT, adapter->tx_fifo_head);			adapter->tx_fifo_head = 0;		}		/* fall through */	case e1000_82571:	case e1000_82572:		if (hw->phy.media_type == e1000_media_type_fiber ||		    hw->phy.media_type == e1000_media_type_internal_serdes) {#define E1000_SERDES_LB_OFF 0x400			ew32(SCTL, E1000_SERDES_LB_OFF);			msleep(10);			break;		}		/* Fall Through */	default:		hw->mac.autoneg = 1;		if (hw->phy.type == e1000_phy_gg82563)			hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,			                          0x180);		if(hw->phy.ops.read_reg)			hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_reg);		if (phy_reg & MII_CR_LOOPBACK) {			phy_reg &= ~MII_CR_LOOPBACK;			hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_reg);			if (hw->phy.ops.commit)				hw->phy.ops.commit(hw);		}		break;	}}static void e1000_create_lbtest_frame(struct sk_buff *skb,				      unsigned int frame_size){

⌨️ 快捷键说明

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