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

📄 e1000_idiag.c

📁 COPE the first practical network coding scheme which is developped on click
💻 C
📖 第 1 页 / 共 3 页
字号:
/*******************************************************************************    Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.    This program is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published by the Free   Software Foundation; either version 2 of the License, or (at your option)   any later version.    This program is distributed in the hope that it will be useful, but WITHOUT   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   more details.    You should have received a copy of the GNU General Public License along with  this program; if not, write to the Free Software Foundation, Inc., 59   Temple Place - Suite 330, Boston, MA  02111-1307, USA.    The full GNU General Public License is included in this distribution in the  file called LICENSE.    Contact Information:  Linux NICS <linux.nics@intel.com>  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************//* * Intel PRO diagnostics */#include "e1000.h"#include "idiag_pro.h"#include "idiag_e1000.h"extern int e1000_up(struct e1000_adapter *adapter);extern void e1000_down(struct e1000_adapter *adapter);extern void e1000_reset(struct e1000_adapter *adapter);#define REG_PATTERN_TEST(R, M, W)                                          \{                                                                          \	uint32_t pat, value;                                               \	uint32_t test[] =                                                  \		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};          \	for(pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) {          \		E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W));     \		value = E1000_READ_REG(&adapter->hw, R);               \		if(value != (test[pat] & W & M)) {                         \			param->reg =                                       \				(adapter->hw.mac_type < e1000_82543) ? \				E1000_82542_##R : E1000_##R;               \			param->write_value = test[pat] & W;                \			param->read_value = value;                         \			return IDIAG_PRO_STAT_TEST_FAILED;                 \		}                                                          \	}                                                                  \}#define REG_SET_AND_CHECK(R, M, W)                                         \{                                                                          \	uint32_t value;                                                    \	E1000_WRITE_REG(&adapter->hw, R, W & M);                       \	value = E1000_READ_REG(&adapter->hw, R);                       \	if ((W & M) != (value & M)) {                                      \		param->reg = (adapter->hw.mac_type < e1000_82543) ?    \			E1000_82542_##R : E1000_##R;                       \		param->write_value = W & M;                                \		param->read_value = value & M;                             \		return IDIAG_PRO_STAT_TEST_FAILED;                         \	}                                                                  \}static enum idiag_pro_state1000_diag_reg_test(struct e1000_adapter *adapter,		    uint8_t *diag_param){	struct idiag_e1000_diag_reg_test_param *param =		(struct idiag_e1000_diag_reg_test_param *) diag_param;	uint32_t value;	uint32_t i;	/* The status register is Read Only, so a write should fail.	 * Some bits that get toggled are ignored.	 */	value = (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833));	E1000_WRITE_REG(&adapter->hw, STATUS, (0xFFFFFFFF));	if(value != (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833))) {		param->reg = E1000_STATUS;		param->write_value = 0xFFFFFFFF;		param->read_value = value;		return IDIAG_PRO_STAT_TEST_FAILED;	}	REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF);	REG_PATTERN_TEST(RDH, 0x0000FFFF, 0x0000FFFF);	REG_PATTERN_TEST(RDT, 0x0000FFFF, 0x0000FFFF);	REG_PATTERN_TEST(FCRTH, 0x0000FFF8, 0x0000FFF8);	REG_PATTERN_TEST(FCTTV, 0x0000FFFF, 0x0000FFFF);	REG_PATTERN_TEST(TIPG, 0x3FFFFFFF, 0x3FFFFFFF);	REG_PATTERN_TEST(TDBAH, 0xFFFFFFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF);	REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);	REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB);	REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);	if(adapter->hw.mac_type >= e1000_82543) {		REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF);		REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);		REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);		REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);		REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);		for(i = 0; i < E1000_RAR_ENTRIES; i++) {			REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF,					 0xFFFFFFFF);			REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,					 0xFFFFFFFF);		}	} else {		REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x01FFFFFF);		REG_PATTERN_TEST(RDBAL, 0xFFFFF000, 0xFFFFFFFF);		REG_PATTERN_TEST(TXCW, 0x0000FFFF, 0x0000FFFF);		REG_PATTERN_TEST(TDBAL, 0xFFFFF000, 0xFFFFFFFF);	}	for(i = 0; i < E1000_MC_TBL_SIZE; i++)		REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);	return IDIAG_PRO_STAT_OK;}static enum idiag_pro_state1000_diag_eeprom_test(struct e1000_adapter *adapter,		       uint8_t *diag_param){	struct idiag_e1000_diag_eeprom_test_param *param =		(struct idiag_e1000_diag_eeprom_test_param *) diag_param;	uint16_t temp;	uint16_t checksum = 0;	uint16_t i;	/* Read and add up the contents of the EEPROM */	for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {		if((e1000_read_eeprom(&adapter->hw, i, &temp)) < 0) {			param->actual_checksum = checksum;			param->expected_checksum = EEPROM_SUM;			return IDIAG_PRO_STAT_TEST_FATAL;		}		checksum += temp;	}	/* If Checksum is not Correct return error else test passed */	if(checksum != (uint16_t) EEPROM_SUM) {		param->actual_checksum = checksum;		param->expected_checksum = EEPROM_SUM;		return IDIAG_PRO_STAT_TEST_FAILED;	}	return IDIAG_PRO_STAT_OK;}static voide1000_diag_intr(int irq,		void *data,		struct pt_regs *regs){	struct net_device *netdev = (struct net_device *) data;	struct e1000_adapter *adapter = netdev->priv;	adapter->diag_icr |= E1000_READ_REG(&adapter->hw, ICR);	return;}static enum idiag_pro_state1000_diag_intr_test(struct e1000_adapter *adapter,		     uint8_t *diag_param){	struct net_device *netdev = adapter->netdev;	enum idiag_e1000_diag_intr_test_param *param =		(enum idiag_e1000_diag_intr_test_param *) diag_param;	uint32_t icr, i, mask;	*param = IDIAG_E1000_INTR_TEST_OK;	/* Hook up diag interrupt handler just for this test */	if(request_irq	   (netdev->irq, &e1000_diag_intr, SA_SHIRQ, netdev->name, netdev))		return IDIAG_PRO_STAT_TEST_FATAL;	/* Disable all the interrupts */	E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);	msec_delay(10);	/* Interrupts are disabled, so read interrupt cause	 * register (icr) twice to verify that there are no interrupts	 * pending.  icr is clear on read.	 */	icr = E1000_READ_REG(&adapter->hw, ICR);	icr = E1000_READ_REG(&adapter->hw, ICR);	if(icr != 0) {		/* if icr is non-zero, there is no point		 * running other interrupt tests.		 */		*param = IDIAG_E1000_INTR_TEST_NOT_EXEC;		return IDIAG_PRO_STAT_TEST_FAILED;	}	/* Test each interrupt */	for(i = 0; i < 10; i++) {		/* Interrupt to test */		mask = 1 << i;		/* Disable the interrupt to be reported in		 * the cause register and then force the same		 * interrupt and see if one gets posted.  If		 * an interrupt was posted to the bus, the		 * test failed.		 */		adapter->diag_icr = 0;		E1000_WRITE_REG(&adapter->hw, IMC, mask);		E1000_WRITE_REG(&adapter->hw, ICS, mask);		msec_delay(10);		if(adapter->diag_icr & mask) {			*param = IDIAG_E1000_INTR_TEST_FAILED_WHILE_DISABLED;			break;		}		/* Enable the interrupt to be reported in		 * 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->diag_icr = 0;		E1000_WRITE_REG(&adapter->hw, IMS, mask);		E1000_WRITE_REG(&adapter->hw, ICS, mask);		msec_delay(10);		if(!(adapter->diag_icr & mask)) {			*param = IDIAG_E1000_INTR_TEST_FAILED_WHILE_ENABLED;			break;		}		/* 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->diag_icr = 0;		E1000_WRITE_REG(&adapter->hw, IMC, ~mask);		E1000_WRITE_REG(&adapter->hw, ICS, ~mask);		msec_delay(10);		if(adapter->diag_icr) {			*param = IDIAG_E1000_INTR_TEST_FAILED_MASKED_ENABLED;			break;		}	}	/* Disable all the interrupts */	E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);	msec_delay(10);	/* Unhook diag interrupt handler */	free_irq(netdev->irq, netdev);	return (*param ==		IDIAG_E1000_INTR_TEST_OK) ? IDIAG_PRO_STAT_OK :		IDIAG_PRO_STAT_TEST_FAILED;}static voide1000_free_desc_rings(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;	if(txdr->desc && txdr->buffer_info) {		for(i = 0; i < txdr->count; i++) {			if(txdr->buffer_info[i].dma)				pci_unmap_single(pdev, txdr->buffer_info[i].dma,						 txdr->buffer_info[i].length,						 PCI_DMA_TODEVICE);			if(txdr->buffer_info[i].skb)				dev_kfree_skb(txdr->buffer_info[i].skb);		}	}	if(rxdr->desc && rxdr->buffer_info) {		for(i = 0; i < rxdr->count; i++) {			if(rxdr->buffer_info[i].dma)				pci_unmap_single(pdev, rxdr->buffer_info[i].dma,						 rxdr->buffer_info[i].length,						 PCI_DMA_FROMDEVICE);			if(rxdr->buffer_info[i].skb)				dev_kfree_skb(rxdr->buffer_info[i].skb);		}	}	if(txdr->desc)		pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma);	if(rxdr->desc)		pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);#if 0	if(txdr->buffer_info)		kfree(txdr->buffer_info);	if(rxdr->buffer_info)		kfree(rxdr->buffer_info);#endif	return;}static inte1000_setup_desc_rings(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;	uint32_t rctl;	int size, i;	/* Setup Tx descriptor ring and Tx buffers */	txdr->count = 80;	size = txdr->count * sizeof(struct e1000_buffer);#if 0	if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL)))		goto err_nomem;#endif

⌨️ 快捷键说明

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