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

📄 eepro100.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010,	RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002,	TxUnderrun=0x1000,  StatusComplete=0x8000,};#define CONFIG_DATA_SIZE 22struct TxFD {					/* Transmit frame descriptor set. */	s32 status;	u32 link;					/* void * */	u32 tx_desc_addr;			/* Always points to the tx_buf_addr element. */	s32 count;					/* # of TBD (=1), Tx start thresh., etc. */	/* This constitutes two "TBD" entries -- we only use one. */#define TX_DESCR_BUF_OFFSET 16	u32 tx_buf_addr0;			/* void *, frame to be transmitted.  */	s32 tx_buf_size0;			/* Length of Tx frame. */	u32 tx_buf_addr1;			/* void *, frame to be transmitted.  */	s32 tx_buf_size1;			/* Length of Tx frame. */	/* the structure must have space for at least CONFIG_DATA_SIZE starting	 * from tx_desc_addr field */};/* Multicast filter setting block.  --SAW */struct speedo_mc_block {	struct speedo_mc_block *next;	unsigned int tx;	dma_addr_t frame_dma;	unsigned int len;	struct descriptor frame __attribute__ ((__aligned__(16)));};/* Elements of the dump_statistics block. This block must be lword aligned. */struct speedo_stats {	u32 tx_good_frames;	u32 tx_coll16_errs;	u32 tx_late_colls;	u32 tx_underruns;	u32 tx_lost_carrier;	u32 tx_deferred;	u32 tx_one_colls;	u32 tx_multi_colls;	u32 tx_total_colls;	u32 rx_good_frames;	u32 rx_crc_errs;	u32 rx_align_errs;	u32 rx_resource_errs;	u32 rx_overrun_errs;	u32 rx_colls_errs;	u32 rx_runt_errs;	u32 done_marker;};enum Rx_ring_state_bits {	RrNoMem=1, RrPostponed=2, RrNoResources=4, RrOOMReported=8,};/* Do not change the position (alignment) of the first few elements!   The later elements are grouped for cache locality.   Unfortunately, all the positions have been shifted since there.   A new re-alignment is required.  2000/03/06  SAW */struct speedo_private {	struct TxFD	*tx_ring;				/* Commands (usually CmdTxPacket). */	struct RxFD *rx_ringp[RX_RING_SIZE];/* Rx descriptor, used as ring. */	/* The addresses of a Tx/Rx-in-place packets/buffers. */	struct sk_buff *tx_skbuff[TX_RING_SIZE];	struct sk_buff *rx_skbuff[RX_RING_SIZE];	/* Mapped addresses of the rings. */	dma_addr_t tx_ring_dma;#define TX_RING_ELEM_DMA(sp, n) ((sp)->tx_ring_dma + (n)*sizeof(struct TxFD))	dma_addr_t rx_ring_dma[RX_RING_SIZE];	struct descriptor *last_cmd;		/* Last command sent. */	unsigned int cur_tx, dirty_tx;		/* The ring entries to be free()ed. */	spinlock_t lock;					/* Group with Tx control cache line. */	u32 tx_threshold;					/* The value for txdesc.count. */	struct RxFD *last_rxf;				/* Last filled RX buffer. */	dma_addr_t last_rxf_dma;	unsigned int cur_rx, dirty_rx;		/* The next free ring entry */	long last_rx_time;			/* Last Rx, in jiffies, to handle Rx hang. */	const char *product_name;	struct net_device_stats stats;	struct speedo_stats *lstats;	dma_addr_t lstats_dma;	int chip_id;	struct pci_dev *pdev;	struct timer_list timer;			/* Media selection timer. */	struct speedo_mc_block *mc_setup_head;/* Multicast setup frame list head. */	struct speedo_mc_block *mc_setup_tail;/* Multicast setup frame list tail. */	int in_interrupt;					/* Word-aligned dev->interrupt */	unsigned char acpi_pwr;	char rx_mode;						/* Current PROMISC/ALLMULTI setting. */	unsigned int tx_full:1;				/* The Tx queue is full. */	unsigned int full_duplex:1;			/* Full-duplex operation requested. */	unsigned int flow_ctrl:1;			/* Use 802.3x flow control. */	unsigned int rx_bug:1;				/* Work around receiver hang errata. */	unsigned char default_port:8;		/* Last dev->if_port value. */	unsigned char rx_ring_state;		/* RX ring status flags. */	unsigned short phy[2];				/* PHY media interfaces available. */	unsigned short advertising;			/* Current PHY advertised caps. */	unsigned short partner;				/* Link partner caps. */};/* The parameters for a CmdConfigure operation.   There are so many options that it would be difficult to document each bit.   We mostly use the default or recommended settings. */const char i82557_config_cmd[CONFIG_DATA_SIZE] = {	22, 0x08, 0, 0,  0, 0, 0x32, 0x03,  1, /* 1=Use MII  0=Use AUI */	0, 0x2E, 0,  0x60, 0,	0xf2, 0x48,   0, 0x40, 0xf2, 0x80, 		/* 0x40=Force full-duplex */	0x3f, 0x05, };const char i82558_config_cmd[CONFIG_DATA_SIZE] = {	22, 0x08, 0, 1,  0, 0, 0x22, 0x03,  1, /* 1=Use MII  0=Use AUI */	0, 0x2E, 0,  0x60, 0x08, 0x88,	0x68, 0, 0x40, 0xf2, 0x84,		/* Disable FC */	0x31, 0x05, };/* PHY media interface chips. */static const char *phys[] = {	"None", "i82553-A/B", "i82553-C", "i82503",	"DP83840", "80c240", "80c24", "i82555",	"unknown-8", "unknown-9", "DP83840A", "unknown-11",	"unknown-12", "unknown-13", "unknown-14", "unknown-15", };enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,					 S80C24, I82555, DP83840A=10, };static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };#define EE_READ_CMD		(6)static int eepro100_init_one(struct pci_dev *pdev,		const struct pci_device_id *ent);static void eepro100_remove_one (struct pci_dev *pdev);#ifdef CONFIG_EEPRO100_PMstatic void eepro100_suspend (struct pci_dev *pdev);static void eepro100_resume (struct pci_dev *pdev);#endifstatic int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);static int mdio_read(long ioaddr, int phy_id, int location);static int mdio_write(long ioaddr, int phy_id, int location, int value);static int speedo_open(struct net_device *dev);static void speedo_resume(struct net_device *dev);static void speedo_timer(unsigned long data);static void speedo_init_rx_ring(struct net_device *dev);static void speedo_tx_timeout(struct net_device *dev);static int speedo_start_xmit(struct sk_buff *skb, struct net_device *dev);static void speedo_refill_rx_buffers(struct net_device *dev, int force);static int speedo_rx(struct net_device *dev);static void speedo_tx_buffer_gc(struct net_device *dev);static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);static int speedo_close(struct net_device *dev);static struct net_device_stats *speedo_get_stats(struct net_device *dev);static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static void set_rx_mode(struct net_device *dev);static void speedo_show_state(struct net_device *dev);#ifdef honor_default_port/* Optional driver feature to allow forcing the transceiver setting.   Not recommended. */static int mii_ctrl[8] = { 0x3300, 0x3100, 0x0000, 0x0100,						   0x2000, 0x2100, 0x0400, 0x3100};#endifstatic int __devinit eepro100_init_one (struct pci_dev *pdev,		const struct pci_device_id *ent){	unsigned long ioaddr;	int irq;	int acpi_idle_state = 0, pm;	static int cards_found /* = 0 */;	static int did_version /* = 0 */;		/* Already printed version info. */	if (speedo_debug > 0  &&  did_version++ == 0)		printk(version);	if (!request_region(pci_resource_start(pdev, 1),			pci_resource_len(pdev, 1), "eepro100")) {		printk (KERN_ERR "eepro100: cannot reserve I/O ports\n");		goto err_out_none;	}	if (!request_mem_region(pci_resource_start(pdev, 0),			pci_resource_len(pdev, 0), "eepro100")) {		printk (KERN_ERR "eepro100: cannot reserve MMIO region\n");		goto err_out_free_pio_region;	}	irq = pdev->irq;#ifdef USE_IO	ioaddr = pci_resource_start(pdev, 1);	if (speedo_debug > 2)		printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",			   ioaddr, irq);#else	ioaddr = (unsigned long)ioremap(pci_resource_start(pdev, 0),									pci_resource_len(pdev, 0));	if (!ioaddr) {		printk (KERN_ERR "eepro100: cannot remap MMIO region %lx @ %lx\n",				pci_resource_len(pdev, 0), pci_resource_start(pdev, 0));		goto err_out_free_mmio_region;	}	if (speedo_debug > 2)		printk("Found Intel i82557 PCI Speedo, MMIO at %#lx, IRQ %d.\n",			   pci_resource_start(pdev, 0), irq);#endif	/* save power state b4 pci_enable_device overwrites it */	pm = pci_find_capability(pdev, PCI_CAP_ID_PM);	if (pm) {		u16 pwr_command;		pci_read_config_word(pdev, pm + PCI_PM_CTRL, &pwr_command);		acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;	}	if (pci_enable_device(pdev))		goto err_out_free_mmio_region;	pci_set_master(pdev);	if (speedo_found1(pdev, ioaddr, cards_found, acpi_idle_state) == 0)		cards_found++;	else		goto err_out_iounmap;	return 0;err_out_iounmap: ;#ifndef USE_IO	iounmap ((void *)ioaddr);#endiferr_out_free_mmio_region:	release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));err_out_free_pio_region:	release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));err_out_none:	return -ENODEV;}static int speedo_found1(struct pci_dev *pdev,		long ioaddr, int card_idx, int acpi_idle_state){	struct net_device *dev;	struct speedo_private *sp;	const char *product;	int i, option;	u16 eeprom[0x100];	int size;	void *tx_ring_space;	dma_addr_t tx_ring_dma;	size = TX_RING_SIZE * sizeof(struct TxFD) + sizeof(struct speedo_stats);	tx_ring_space = pci_alloc_consistent(pdev, size, &tx_ring_dma);	if (tx_ring_space == NULL)		return -1;	dev = init_etherdev(NULL, sizeof(struct speedo_private));	if (dev == NULL) {		printk(KERN_ERR "eepro100: Could not allocate ethernet device.\n");		pci_free_consistent(pdev, size, tx_ring_space, tx_ring_dma);		return -1;	}	if (dev->mem_start > 0)		option = dev->mem_start;	else if (card_idx >= 0  &&  options[card_idx] >= 0)		option = options[card_idx];	else		option = 0;	/* Read the station address EEPROM before doing the reset.	   Nominally his should even be done before accepting the device, but	   then we wouldn't have a device name with which to report the error.	   The size test is for 6 bit vs. 8 bit address serial EEPROMs.	*/	{		unsigned long iobase;		int read_cmd, ee_size;		u16 sum;		int j;		/* Use IO only to avoid postponed writes and satisfy EEPROM timing		   requirements. */		iobase = pci_resource_start(pdev, 1);		if ((do_eeprom_cmd(iobase, EE_READ_CMD << 24, 27) & 0xffe0000)			== 0xffe0000) {			ee_size = 0x100;			read_cmd = EE_READ_CMD << 24;		} else {			ee_size = 0x40;			read_cmd = EE_READ_CMD << 22;		}		for (j = 0, i = 0, sum = 0; i < ee_size; i++) {			u16 value = do_eeprom_cmd(iobase, read_cmd | (i << 16), 27);			eeprom[i] = value;			sum += value;			if (i < 3) {				dev->dev_addr[j++] = value;				dev->dev_addr[j++] = value >> 8;			}		}		if (sum != 0xBABA)			printk(KERN_WARNING "%s: Invalid EEPROM checksum %#4.4x, "				   "check settings before activating this device!\n",				   dev->name, sum);		/* Don't  unregister_netdev(dev);  as the EEPro may actually be		   usable, especially if the MAC address is set later.		   On the other hand, it may be unusable if MDI data is corrupted. */	}	/* Reset the chip: stop Tx and Rx processes and clear counters.	   This takes less than 10usec and will easily finish before the next	   action. */	outl(PortReset, ioaddr + SCBPort);	udelay(10);	if (eeprom[3] & 0x0100)		product = "OEM i82557/i82558 10/100 Ethernet";	else		product = pdev->name;	printk(KERN_INFO "%s: %s, ", dev->name, product);	for (i = 0; i < 5; i++)		printk("%2.2X:", dev->dev_addr[i]);	printk("%2.2X, ", dev->dev_addr[i]);#ifdef USE_IO	printk("I/O at %#3lx, ", ioaddr);#endif	printk("IRQ %d.\n", pdev->irq);#if 1 || defined(kernel_bloat)	/* OK, this is pure kernel bloat.  I don't like it when other drivers	   waste non-pageable kernel space to emit similar messages, but I need	   them for bug reports. */	{		const char *connectors[] = {" RJ45", " BNC", " AUI", " MII"};		/* The self-test results must be paragraph aligned. */		volatile s32 *self_test_results;		int boguscnt = 16000;	/* Timeout for set-test. */		if (eeprom[3] & 0x03)			printk(KERN_INFO "  Receiver lock-up bug exists -- enabling"				   " work-around.\n");		printk(KERN_INFO "  Board assembly %4.4x%2.2x-%3.3d, Physical"			   " connectors present:",			   eeprom[8], eeprom[9]>>8, eeprom[9] & 0xff);		for (i = 0; i < 4; i++)			if (eeprom[5] & (1<<i))				printk(connectors[i]);		printk("\n"KERN_INFO"  Primary interface chip %s PHY #%d.\n",			   phys[(eeprom[6]>>8)&15], eeprom[6] & 0x1f);		if (eeprom[7] & 0x0700)			printk(KERN_INFO "    Secondary interface chip %s.\n",				   phys[(eeprom[7]>>8)&7]);		if (((eeprom[6]>>8) & 0x3f) == DP83840			||  ((eeprom[6]>>8) & 0x3f) == DP83840A) {			int mdi_reg23 = mdio_read(ioaddr, eeprom[6] & 0x1f, 23) | 0x0422;			if (congenb)			  mdi_reg23 |= 0x0100;			printk(KERN_INFO"  DP83840 specific setup, setting register 23 to %4.4x.\n",				   mdi_reg23);			mdio_write(ioaddr, eeprom[6] & 0x1f, 23, mdi_reg23);		}		if ((option >= 0) && (option & 0x70)) {			printk(KERN_INFO "  Forcing %dMbs %s-duplex operation.\n",				   (option & 0x20 ? 100 : 10),				   (option & 0x10 ? "full" : "half"));			mdio_write(ioaddr, eeprom[6] & 0x1f, 0,					   ((option & 0x20) ? 0x2000 : 0) | 	/* 100mbps? */					   ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */		}		/* Perform a system self-test. */		self_test_results = (s32*) ((((long) tx_ring_space) + 15) & ~0xf);		self_test_results[0] = 0;		self_test_results[1] = -1;		outl(tx_ring_dma | PortSelfTest, ioaddr + SCBPort);		do {			udelay(10);		} while (self_test_results[1] == -1  &&  --boguscnt >= 0);		if (boguscnt < 0) {		/* Test optimized out. */			printk(KERN_ERR "Self test failed, status %8.8x:\n"				   KERN_ERR " Failure to initialize the i82557.\n"				   KERN_ERR " Verify that the card is a bus-master"				   " capable slot.\n",				   self_test_results[1]);		} else			printk(KERN_INFO "  General self-test: %s.\n"				   KERN_INFO "  Serial sub-system self-test: %s.\n"

⌨️ 快捷键说明

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