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

📄 eepro100.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
static struct enet_statistics *speedo_get_stats(struct device *dev);static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd);static void set_rx_mode(struct device *dev);/* The parameters that may be passed in... *//* 'options' is used to pass a transceiver override or full-duplex flag   e.g. "options=16" for FD, "options=32" for 100mbps-only. */static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};#ifdef MODULEstatic int debug = -1;			/* The debug level */#endif#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};#endif/* A list of all installed Speedo devices, for removing the driver module. */static struct device *root_speedo_dev = NULL;int eepro100_init(struct device *dev){	int cards_found = 0;	static int pci_index = 0;	if (! pcibios_present())		return cards_found;	for (; pci_index < 8; pci_index++) {		unsigned char pci_bus, pci_device_fn, pci_latency;		long ioaddr;		int irq;		u16 pci_command, new_command;		if (pcibios_find_device(PCI_VENDOR_ID_INTEL,								PCI_DEVICE_ID_INTEL_82557,								pci_index, &pci_bus,								&pci_device_fn))			break;		{			struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);			ioaddr = pdev->base_address[1];		/* Use [0] to mem-map */			irq = pdev->irq;		}		/* Remove I/O space marker in bit 0. */		ioaddr &= ~3;		if (speedo_debug > 2)			printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",				   ioaddr, irq);		/* Get and check the bus-master and latency values. */		pcibios_read_config_word(pci_bus, pci_device_fn,								 PCI_COMMAND, &pci_command);		new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;		if (pci_command != new_command) {			printk(KERN_INFO "  The PCI BIOS has not enabled this"				   " device!  Updating PCI command %4.4x->%4.4x.\n",				   pci_command, new_command);			pcibios_write_config_word(pci_bus, pci_device_fn,									  PCI_COMMAND, new_command);		}		pcibios_read_config_byte(pci_bus, pci_device_fn,								 PCI_LATENCY_TIMER, &pci_latency);		if (pci_latency < 32) {			printk("  PCI latency timer (CFLT) is unreasonably low at %d."				   "  Setting to 32 clocks.\n", pci_latency);			pcibios_write_config_byte(pci_bus, pci_device_fn,									  PCI_LATENCY_TIMER, 32);		} else if (speedo_debug > 1)			printk("  PCI latency timer (CFLT) is %#x.\n", pci_latency);		speedo_found1(dev, ioaddr, irq, cards_found);		dev = NULL;		cards_found++;	}	return cards_found;}static void speedo_found1(struct device *dev, long ioaddr, int irq,						  int card_idx){	static int did_version = 0;			/* Already printed version info. */	struct speedo_private *sp;	char *product;	int i, option;	u16 eeprom[0x40];	if (speedo_debug > 0  &&  did_version++ == 0)		printk(version);	dev = init_etherdev(dev, sizeof(struct speedo_private));	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.	   Perhaps this should even be done before accepting the device,	   then we wouldn't have a device name with which to report the error. */	{		u16 sum = 0;		int j;		int addr_len = read_eeprom(ioaddr, 0, 6) == 0xffff ? 8 : 6;		for (j = 0, i = 0; i < 0x40; i++) {			u16 value = read_eeprom(ioaddr, i, addr_len);			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. */	}	/* 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(0, ioaddr + SCBPort);	if (eeprom[3] & 0x0100)		product = "OEM i82557/i82558 10/100 Ethernet";	else		product = "Intel EtherExpress Pro 10/100";	printk(KERN_INFO "%s: %s at %#3lx, ", dev->name, product, ioaddr);	for (i = 0; i < 5; i++)		printk("%2.2X:", dev->dev_addr[i]);	printk("%2.2X, IRQ %d.\n", dev->dev_addr[i], irq);#ifndef 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. */		s32 str[6], *volatile 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) str) + 15) & ~0xf);		self_test_results[0] = 0;		self_test_results[1] = -1;		outl(virt_to_bus(self_test_results) | 1, 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"				   KERN_INFO "  Internal registers self-test: %s.\n"				   KERN_INFO "  ROM checksum self-test: %s (%#8.8x).\n",				   self_test_results[1] & 0x1000 ? "failed" : "passed",				   self_test_results[1] & 0x0020 ? "failed" : "passed",				   self_test_results[1] & 0x0008 ? "failed" : "passed",				   self_test_results[1] & 0x0004 ? "failed" : "passed",				   self_test_results[0]);	}#endif  /* kernel_bloat */	/* We do a request_region() only to register /proc/ioports info. */	request_region(ioaddr, SPEEDO3_TOTAL_SIZE, "Intel Speedo3 Ethernet");	dev->base_addr = ioaddr;	dev->irq = irq;	if (dev->priv == NULL)		dev->priv = kmalloc(sizeof(*sp), GFP_KERNEL);	sp = dev->priv;	memset(sp, 0, sizeof(*sp));	sp->next_module = root_speedo_dev;	root_speedo_dev = dev;	sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;	if (card_idx >= 0) {		if (full_duplex[card_idx] >= 0)			sp->full_duplex = full_duplex[card_idx];	}	sp->default_port = option >= 0 ? (option & 0x0f) : 0;	sp->phy[0] = eeprom[6];	sp->phy[1] = eeprom[7];	sp->rx_bug = (eeprom[3] & 0x03) == 3 ? 0 : 1;	if (sp->rx_bug)		printk(KERN_INFO "  Receiver lock-up workaround activated.\n");	/* The Speedo-specific entries in the device structure. */	dev->open = &speedo_open;	dev->hard_start_xmit = &speedo_start_xmit;	dev->stop = &speedo_close;	dev->get_stats = &speedo_get_stats;	dev->set_multicast_list = &set_rx_mode;	dev->do_ioctl = &speedo_ioctl;	return;}/* Serial EEPROM section.   A "bit" grungy, but we work our way through bit-by-bit :->. *//*  EEPROM_Ctrl bits. */#define EE_SHIFT_CLK	0x01	/* EEPROM shift clock. */#define EE_CS			0x02	/* EEPROM chip select. */#define EE_DATA_WRITE	0x04	/* EEPROM chip data in. */#define EE_WRITE_0		0x01#define EE_WRITE_1		0x05#define EE_DATA_READ	0x08	/* EEPROM chip data out. */#define EE_ENB			(0x4800 | EE_CS)/* Delay between EEPROM clock transitions.   This will actually work with no delay on 33Mhz PCI.  */#define eeprom_delay(nanosec)		udelay(1);/* The EEPROM commands include the alway-set leading bit. */#define EE_WRITE_CMD	(5 << addr_len)#define EE_READ_CMD		(6 << addr_len)#define EE_ERASE_CMD	(7 << addr_len)static int read_eeprom(long ioaddr, int location, int addr_len){	unsigned short retval = 0;	int ee_addr = ioaddr + SCBeeprom;	int read_cmd = location | EE_READ_CMD;	int i;	outw(EE_ENB & ~EE_CS, ee_addr);	outw(EE_ENB, ee_addr);	/* Shift the read command bits out. */	for (i = 12; i >= 0; i--) {		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;		outw(EE_ENB | dataval, ee_addr);		eeprom_delay(100);		outw(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);		eeprom_delay(150);	}	outw(EE_ENB, ee_addr);	for (i = 15; i >= 0; i--) {		outw(EE_ENB | EE_SHIFT_CLK, ee_addr);		eeprom_delay(100);		retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);		outw(EE_ENB, ee_addr);		eeprom_delay(100);	}	/* Terminate the EEPROM access. */	outw(EE_ENB & ~EE_CS, ee_addr);	return retval;}static int mdio_read(long ioaddr, int phy_id, int location){	int val, boguscnt = 64*10;		/* <64 usec. to complete, typ 27 ticks */	outl(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI);	do {		val = inl(ioaddr + SCBCtrlMDI);		if (--boguscnt < 0) {			printk(KERN_ERR " mdio_read() timed out with val = %8.8x.\n", val);		}	} while (! (val & 0x10000000));	return val & 0xffff;}static int mdio_write(long ioaddr, int phy_id, int location, int value){	int val, boguscnt = 64*10;		/* <64 usec. to complete, typ 27 ticks */	outl(0x04000000 | (location<<16) | (phy_id<<21) | value,		 ioaddr + SCBCtrlMDI);	do {		val = inl(ioaddr + SCBCtrlMDI);		if (--boguscnt < 0) {			printk(KERN_ERR" mdio_write() timed out with val = %8.8x.\n", val);		}	} while (! (val & 0x10000000));	return val & 0xffff;}static intspeedo_open(struct device *dev){	struct speedo_private *sp = (struct speedo_private *)dev->priv;	long ioaddr = dev->base_addr;#ifdef notdef	/* We could reset the chip, but should not need to. */	/* In fact we MUST NOT, unless we also re-do the init */	outl(0, ioaddr + SCBPort);	udelay(10);#endif	/* This had better be initialized before we initialize the interrupt! */	sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;	if (speedo_debug > 1)		printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);#ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us	/* Retrigger negotiation to reset previous errors. */	if ((sp->phy[0] & 0x8000) == 0) {		int phy_addr = sp->phy[0] & 0x1f ;		/* Use 0x3300 for restarting NWay, other values to force xcvr:		   0x0000 10-HD		   0x0100 10-FD		   0x2000 100-HD		   0x2100 100-FD		*/#ifdef honor_default_port		mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]);#else		mdio_write(ioaddr, phy_addr, 0, 0x3300);#endif	}#endif	/* Load the statistics block address. */	wait_for_cmd_done(ioaddr + SCBCmd);	outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer);	outw(INT_MASK | CU_STATSADDR, ioaddr + SCBCmd);	sp->lstats.done_marker = 0;	speedo_init_rx_ring(dev);	wait_for_cmd_done(ioaddr + SCBCmd);	outl(0, ioaddr + SCBPointer);	outw(INT_MASK | RX_ADDR_LOAD, ioaddr + SCBCmd);	/* Todo: verify that we must wait for previous command completion. */	wait_for_cmd_done(ioaddr + SCBCmd);	outl(virt_to_bus(sp->rx_ringp[0]), ioaddr + SCBPointer);	outw(INT_MASK | RX_START, ioaddr + SCBCmd);	/* Fill the first command with our physical address. */	{		u16 *eaddrs = (u16 *)dev->dev_addr;		u16 *setup_frm = (u16 *)&(sp->tx_ring[0].tx_desc_addr);		/* Avoid a bug(?!) here by marking the command already completed. */		sp->tx_ring[0].status = ((CmdSuspend | CmdIASetup) << 16) | 0xa000;		sp->tx_ring[0].link = virt_to_bus(&(sp->tx_ring[1]));		*setup_frm++ = eaddrs[0];		*setup_frm++ = eaddrs[1];		*setup_frm++ = eaddrs[2];	}	sp->last_cmd = (struct descriptor *)&sp->tx_ring[0];	sp->cur_tx = 1;	sp->dirty_tx = 0;	sp->tx_full = 0;	wait_for_cmd_done(ioaddr + SCBCmd);	outl(0, ioaddr + SCBPointer);	outw(INT_MASK | CU_CMD_BASE, ioaddr + SCBCmd);

⌨️ 快捷键说明

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