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

📄 eepro100_cb.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 5 页
字号:
		product = pci_id_tbl[chip_idx].name;	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) | 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"				   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 */	outl(PortReset, ioaddr + SCBPort);	/* Return the chip to its original power state. */	acpi_set_pwr_state(pdev, acpi_idle_state);	/* We do a request_region() only to register /proc/ioports info. */	request_region(ioaddr, pci_id_tbl[chip_idx].io_size, "Intel Speedo3 Ethernet");	dev->base_addr = ioaddr;	dev->irq = irq;	sp = dev->priv;	if (dev->priv == NULL) {		void *mem = kmalloc(sizeof(*sp), GFP_KERNEL);		dev->priv = sp = mem;		/* Cache align here if kmalloc does not. */		sp->priv_addr = mem;	}	memset(sp, 0, sizeof(*sp));	sp->next_module = root_speedo_dev;	root_speedo_dev = dev;	sp->pci_dev = pdev;	sp->chip_id = chip_idx;	sp->acpi_pwr = acpi_idle_state;	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;#ifdef HAVE_TX_TIMEOUT	dev->watchdog_timeo = TX_TIMEOUT;	dev->tx_timeout = speedo_tx_timeout;#endif	return dev;}/* 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_DATA_READ	0x08	/* EEPROM chip data out. */#define EE_ENB			(0x4800 | EE_CS)#define EE_WRITE_0		0x4802#define EE_WRITE_1		0x4806#define EE_OFFSET		SCBeeprom/* Delay between EEPROM clock transitions.   The code works with no delay on 33Mhz PCI.  */#define eeprom_delay()	inw(ee_addr)static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len){	unsigned retval = 0;	long ee_addr = ioaddr + SCBeeprom;	outw(EE_ENB | EE_SHIFT_CLK, ee_addr);	/* Shift the command bits out. */	do {		short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;		outw(dataval, ee_addr);		eeprom_delay();		outw(dataval | EE_SHIFT_CLK, ee_addr);		eeprom_delay();		retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);	} while (--cmd_len >= 0);	outw(EE_ENB, ee_addr);	/* 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);			break;		}	} 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);			break;		}	} while (! (val & 0x10000000));	return val & 0xffff;}static intspeedo_open(struct net_device *dev){	struct speedo_private *sp = (struct speedo_private *)dev->priv;	long ioaddr = dev->base_addr;	acpi_set_pwr_state(sp->pci_dev, ACPI_D0);	if (speedo_debug > 1)		printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);	/* Set up the Tx queue early.. */	sp->cur_tx = 0;	sp->dirty_tx = 0;	sp->last_cmd = 0;	sp->tx_full = 0;	sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;	/* .. we can safely take handler calls during init. */	if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) {		return -EAGAIN;	}	MOD_INC_USE_COUNT;	dev->if_port = sp->default_port;#if 0	/* With some transceivers we must retrigger negotiation to reset	   power-up 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	speedo_init_rx_ring(dev);	/* Fire up the hardware. */	speedo_resume(dev);	netif_start_queue(dev);	netif_mark_up(dev);	/* Setup the chip and configure the multicast list. */	sp->mc_setup_frm = NULL;	sp->mc_setup_frm_len = 0;	sp->mc_setup_busy = 0;	sp->rx_mode = -1;			/* Invalid -> always reset the mode. */	sp->flow_ctrl = sp->partner = 0;	set_rx_mode(dev);	if ((sp->phy[0] & 0x8000) == 0)		sp->advertising = mdio_read(ioaddr, sp->phy[0] & 0x1f, 4);	if (speedo_debug > 2) {		printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n",			   dev->name, inw(ioaddr + SCBStatus));	}	/* Set the timer.  The timer serves a dual purpose:	   1) to monitor the media interface (e.g. link beat) and perhaps switch	   to an alternate media type	   2) to monitor Rx activity, and restart the Rx process if the receiver	   hangs. */	init_timer(&sp->timer);	sp->timer.expires = jiffies + 3*HZ;	sp->timer.data = (unsigned long)dev;	sp->timer.function = &speedo_timer;					/* timer handler */	add_timer(&sp->timer);	/* No need to wait for the command unit to accept here. */	if ((sp->phy[0] & 0x8000) == 0)		mdio_read(ioaddr, sp->phy[0] & 0x1f, 0);	return 0;}/* Start the chip hardware after a full reset. */static void speedo_resume(struct net_device *dev){	struct speedo_private *sp = (struct speedo_private *)dev->priv;	long ioaddr = dev->base_addr;	outw(SCBMaskAll, ioaddr + SCBCmd);	/* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */	sp->tx_threshold = 0x01208000;	/* Set the segment registers to '0'. */	wait_for_cmd_done(ioaddr + SCBCmd);	outl(0, ioaddr + SCBPointer);	outb(RxAddrLoad, ioaddr + SCBCmd);	wait_for_cmd_done(ioaddr + SCBCmd);	outb(CUCmdBase, ioaddr + SCBCmd);	wait_for_cmd_done(ioaddr + SCBCmd);	/* Load the statistics block and rx ring addresses. */	outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer);	outb(CUStatsAddr, ioaddr + SCBCmd);	sp->lstats.done_marker = 0;	wait_for_cmd_done(ioaddr + SCBCmd);	outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]),		 ioaddr + SCBPointer);	outb(RxStart, ioaddr + SCBCmd);	wait_for_cmd_done(ioaddr + SCBCmd);	outb(CUDumpStats, ioaddr + SCBCmd);	/* Fill the first command with our physical address. */	{		int entry = sp->cur_tx++ % TX_RING_SIZE;		struct descriptor *cur_cmd = (struct descriptor *)&sp->tx_ring[entry];		/* Avoid a bug(?!) here by marking the command already completed. */		cur_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000);		cur_cmd->link =			virt_to_le32desc(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]);		memcpy(cur_cmd->params, dev->dev_addr, 6);		if (sp->last_cmd)			clear_suspend(sp->last_cmd);		sp->last_cmd = cur_cmd;	}	/* Start the chip's Tx process and unmask interrupts. */	wait_for_cmd_done(ioaddr + SCBCmd);	outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]),		 ioaddr + SCBPointer);	outw(CUStart, ioaddr + SCBCmd);}/* Media monitoring and control. */static void speedo_timer(unsigned long data){	struct net_device *dev = (struct net_device *)data;	struct speedo_private *sp = (struct speedo_private *)dev->priv;	long ioaddr = dev->base_addr;	int phy_num = sp->phy[0] & 0x1f;	/* We have MII and lost link beat. */	if ((sp->phy[0] & 0x8000) == 0) {		int partner = mdio_read(ioaddr, phy_num, 5);		if (partner != sp->partner) {			int flow_ctrl = sp->advertising & partner & 0x0400 ? 1 : 0;			sp->partner = partner;			if (flow_ctrl != sp->flow_ctrl) {				sp->flow_ctrl = flow_ctrl;				sp->rx_mode = -1;	/* Trigger a reload. */			}			/* Clear sticky bit. */			mdio_read(ioaddr, phy_num, 1);			/* If link beat has returned... */			if (mdio_read(ioaddr, phy_num, 1) & 0x0004)				dev->flags |= IFF_RUNNING;			else				dev->flags &= ~IFF_RUNNING;		}	}	if (speedo_debug > 3) {		printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n",			   dev->name, inw(ioaddr + SCBStatus));	}	/* This no longer has a false-trigger window. */     if (sp->cur_tx - sp->dirty_tx > 1 &&		(jiffies - dev->trans_start) > TX_TIMEOUT  &&		(jiffies - sp->last_cmd_time) > TX_TIMEOUT) {		 printk(KERN_DEBUG "%d %d %d %d\n", 			 sp->cur_tx - sp->dirty_tx,		     jiffies - dev->trans_start,				jiffies - sp->last_cmd_time,				TX_TIMEOUT);		speedo_tx_timeout(dev);		sp->last_reset = jiffies;	  }	if (sp->rx_mode < 0  ||		(sp->rx_bug  && jiffies - sp->last_rx_time > 2*HZ)) {

⌨️ 快捷键说明

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