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

📄 e1000_idiag.c

📁 COPE the first practical network coding scheme which is developped on click
💻 C
📖 第 1 页 / 共 3 页
字号:
				    M88E1000_EXT_PHY_SPEC_CTRL, 0x0c04);		/* reset to update MAC interface speed */		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8100);		/* force 10, set loopback */		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4100);		/* Now set up the MAC to the same speed/duplex as the PHY. */		ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);		ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */		ctrl_reg |= (E1000_CTRL_SLU |	/* Set the Force Link Bit */			     E1000_CTRL_FRCSPD |/* Set the Force Speed Bit */			     E1000_CTRL_FRCDPX |/* Set the Force Duplex Bit */			     E1000_CTRL_SPD_10 |/* Force Speed to 10 */			     E1000_CTRL_FD);	/* Force Duplex to FULL */		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);		loopback_mode_set = TRUE;		break;	default:		loopback_mode_set = FALSE;		break;	}	/* 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.	 */	e1000_phy_disable_receiver(adapter);	usec_delay(500);	return loopback_mode_set ? 0 : 1;}/** * e1000_set_phy_loopback - Set the PHY into loopback mode. * @adapter: board private structure * * Returns 0 on success, 1 on failure **/static inte1000_set_phy_loopback(struct e1000_adapter *adapter){	uint16_t phy_reg = 0;	uint16_t speed = 0;	uint16_t duplex = 0;	int status = 1;	int count;	switch (adapter->hw.mac_type) {	case e1000_82543:		if(adapter->hw.media_type == e1000_media_type_copper) {			/* Attempt to setup Loopback mode on Non-			 * integrated PHY.  Some PHY registers get			 * corrupted at random, so attempt this			 * 10 times.			 */			for(count = 0; count < 10; count++)				if(!e1000_nonintegrated_phy_loopback(adapter))					break;			status = 0;		}		break;	case e1000_82544:		if(adapter->hw.media_type == e1000_media_type_copper)			e1000_get_speed_and_duplex(&adapter->hw, &speed,			                           &duplex);			status = e1000_integrated_phy_loopback(adapter, speed);		break;	case e1000_82540:	case e1000_82545:	case e1000_82546:		e1000_get_speed_and_duplex(&adapter->hw, &speed, &duplex);		status = e1000_integrated_phy_loopback(adapter, speed);		break;	default:		/* Default PHY loopback work is to read the MII 		 * control register and assert bit 14 (loopback mode).		 */		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);		phy_reg |= MII_CR_LOOPBACK;		e1000_write_phy_reg(&adapter->hw, PHY_CTRL,				    phy_reg);		status = 0;		break;	}	return status;}static inte1000_set_loopback_mode(struct e1000_adapter *adapter,			enum idiag_e1000_diag_loopback_mode mode){	uint32_t rctl;	uint16_t phy_reg;	int status = 1;	switch (mode) {	case IDIAG_E1000_DIAG_NONE_LB:		/* Clear bits 7:6 to turn off loopback mode */		rctl = E1000_READ_REG(&adapter->hw, RCTL);		rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);		E1000_WRITE_REG(&adapter->hw, RCTL, rctl);		/* Only modify the GMII/MII PHY device if the		 * media type is copper.		 */		if(adapter->hw.media_type == e1000_media_type_copper ||		  (adapter->hw.media_type == e1000_media_type_fiber &&		  (adapter->hw.mac_type == e1000_82545 ||		   adapter->hw.mac_type == e1000_82546))) {			adapter->hw.autoneg = TRUE;			/* De-assert bit 14 (loopback mode) in PHY */			e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);			/* Only turn off PHY loopback if enabled */			if(phy_reg & MII_CR_LOOPBACK) {				phy_reg &= ~MII_CR_LOOPBACK;				e1000_write_phy_reg(&adapter->hw, PHY_CTRL,						    phy_reg);				/* Reset the PHY to make sure we				 * regain link */				e1000_phy_reset(&adapter->hw);			}		}		status = 0;		break;	case IDIAG_E1000_DIAG_MAC_LB:		/* Not supported */		break;	case IDIAG_E1000_DIAG_PHY_TCVR_LB:		if(adapter->hw.media_type == e1000_media_type_fiber) {			if(adapter->hw.mac_type == e1000_82545 ||			   adapter->hw.mac_type == e1000_82546) {				status = e1000_set_phy_loopback(adapter);			} else {				rctl = E1000_READ_REG(&adapter->hw, RCTL);				rctl |= E1000_RCTL_LBM_TCVR;				E1000_WRITE_REG(&adapter->hw, RCTL, rctl);				status = 0;			}		}		if(adapter->hw.media_type == e1000_media_type_copper) {			status = e1000_set_phy_loopback(adapter);		}		break;	}	return status;}static voide1000_create_lbtest_frame(struct sk_buff *skb,			  unsigned int frame_size){	memset(skb->data, 0xFF, frame_size);	frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;	memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);	memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);	memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);}static inte1000_check_lbtest_frame(struct sk_buff *skb,			 unsigned int frame_size){	frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;	if(*(skb->data + 3) == 0xFF) {		if((*(skb->data + frame_size / 2 + 10) == 0xBE) &&		   (*(skb->data + frame_size / 2 + 12) == 0xAF)) {			return 1;		}	}	return 0;}static enum idiag_e1000_diag_loopback_resulte1000_loopback_test(struct e1000_adapter *adapter){	struct e1000_desc_ring *txdr = &adapter->diag_tx_ring;	struct e1000_desc_ring *rxdr = &adapter->diag_rx_ring;	struct pci_dev *pdev = adapter->pdev;	int i;	E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);	for(i = 0; i < 64; i++) {		e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024);		pci_dma_sync_single(pdev, txdr->buffer_info[i].dma,				    txdr->buffer_info[i].length,				    PCI_DMA_TODEVICE);	}	E1000_WRITE_REG(&adapter->hw, TDT, i);	msec_delay(200);	pci_dma_sync_single(pdev, rxdr->buffer_info[0].dma,			    rxdr->buffer_info[0].length, PCI_DMA_FROMDEVICE);	if(e1000_check_lbtest_frame(rxdr->buffer_info[0].skb, 1024))		return IDIAG_E1000_LOOPBACK_TEST_OK;	else		return IDIAG_E1000_LOOPBACK_TEST_FAILED;}static enum idiag_pro_state1000_diag_loopback_test(struct e1000_adapter *adapter,			 uint8_t *diag_param){	struct idiag_e1000_diag_loopback_test_param *param =		(struct idiag_e1000_diag_loopback_test_param *) diag_param;	if(param->mode == IDIAG_E1000_DIAG_MAC_LB) {		/* Loopback test not support */		param->result = IDIAG_E1000_LOOPBACK_TEST_NOT_EXEC;		return IDIAG_PRO_STAT_NOT_SUPPORTED;	}	if(e1000_setup_desc_rings(adapter)) {		param->result = IDIAG_E1000_LOOPBACK_TEST_NOT_EXEC;		return IDIAG_PRO_STAT_TEST_FAILED;	}	if(e1000_set_loopback_mode(adapter, param->mode)) {		param->result = IDIAG_E1000_LOOPBACK_TEST_NOT_EXEC;		e1000_free_desc_rings(adapter);		return IDIAG_PRO_STAT_TEST_FAILED;	}	param->result = e1000_loopback_test(adapter);	e1000_set_loopback_mode(adapter, IDIAG_E1000_DIAG_NONE_LB);	e1000_free_desc_rings(adapter);	return (param->result ==		IDIAG_E1000_LOOPBACK_TEST_OK) ? IDIAG_PRO_STAT_OK :		IDIAG_PRO_STAT_TEST_FAILED;}static enum idiag_pro_state1000_diag_link_test(struct e1000_adapter *adapter,		     uint8_t *diag_param){	e1000_check_for_link(&adapter->hw);	if(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)		return IDIAG_PRO_STAT_OK;	else		return IDIAG_PRO_STAT_TEST_FAILED;}inte1000_diag_ioctl(struct net_device *netdev,		 struct ifreq *ifr){	struct e1000_adapter *adapter = netdev->priv;	struct idiag_pro_data *diag_data =		(struct idiag_pro_data *) ifr->ifr_data;	boolean_t run_offline;	boolean_t interface_up = netif_running(netdev);	diag_data->status = IDIAG_PRO_STAT_NOT_SUPPORTED;	if(!capable(CAP_NET_ADMIN))		/* must have admin capabilities */		return -EPERM;	if(diag_data->interface_ver != IDIAG_PRO_VERSION)		/* incorrect diagnostics interface version */		return -EFAULT;	if(diag_data->cmd != IDIAG_PRO_IDENTIFY_DRIVER &&	   diag_data->driver_id != IDIAG_E1000_DRIVER)		/* incorrect driver identifier */		return -EFAULT;	/* Some test requring exclusive access to hardware, so	 * we need to teardown the hardware setup, run the test,	 * and restore the hardware to resume the network 	 * connection. 	 */	run_offline =  (diag_data->cmd == IDIAG_E1000_DIAG_REG_TEST ||			diag_data->cmd == IDIAG_E1000_DIAG_INTR_TEST ||			diag_data->cmd == IDIAG_E1000_DIAG_LOOPBACK_TEST);	if(run_offline) {		if(interface_up)			e1000_down(adapter);		else			e1000_reset(adapter);	}	/* Run the diagnotic test */	switch (diag_data->cmd) {	case IDIAG_PRO_IDENTIFY_DRIVER:		diag_data->driver_id = IDIAG_E1000_DRIVER;		diag_data->status = IDIAG_PRO_STAT_OK;		break;	case IDIAG_E1000_DIAG_REG_TEST:		diag_data->status =			e1000_diag_reg_test(adapter, diag_data->diag_param);		break;	case IDIAG_E1000_DIAG_XSUM_TEST:		diag_data->status =			e1000_diag_eeprom_test(adapter, diag_data->diag_param);		break;	case IDIAG_E1000_DIAG_INTR_TEST:		diag_data->status =			e1000_diag_intr_test(adapter, diag_data->diag_param);		break;	case IDIAG_E1000_DIAG_LOOPBACK_TEST:		diag_data->status =			e1000_diag_loopback_test(adapter,						 diag_data->diag_param);		break;	case IDIAG_E1000_DIAG_LINK_TEST:		diag_data->status =			e1000_diag_link_test(adapter, diag_data->diag_param);		break;	default:		diag_data->status = IDIAG_PRO_STAT_NOT_SUPPORTED;		break;	}	if(run_offline) {		e1000_reset(adapter);		if(interface_up) {			if(e1000_up(adapter)) {				diag_data->status = IDIAG_PRO_STAT_TEST_FATAL;				return -EFAULT;			}		}	}	return 0;}

⌨️ 快捷键说明

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