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

📄 eexpress.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 3 页
字号:
static unsigned short eexp_hw_lasttxstat(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	unsigned short ioaddr = dev->base_addr;	unsigned short old_rp = inw(ioaddr+READ_PTR);	unsigned short old_wp = inw(ioaddr+WRITE_PTR);	unsigned short tx_block = lp->tx_reap;	unsigned short status;  	if (!test_bit(0,(void *)&dev->tbusy) && lp->tx_head==lp->tx_reap) 		return 0x0000;	do	{		outw(tx_block,ioaddr+READ_PTR);		status = inw(ioaddr);		if (!Stat_Done(status)) 		{			lp->tx_link = tx_block;			outw(old_rp,ioaddr+READ_PTR);			outw(old_wp,ioaddr+WRITE_PTR);			return status;		}		else 		{			lp->last_tx_restart = 0;			lp->stats.collisions += Stat_NoColl(status);			if (!Stat_OK(status)) 			{				if (Stat_Abort(status)) 					lp->stats.tx_aborted_errors++;				if (Stat_TNoCar(status) || Stat_TNoCTS(status)) 					lp->stats.tx_carrier_errors++;				if (Stat_TNoDMA(status)) 					lp->stats.tx_fifo_errors++;			}			else				lp->stats.tx_packets++;		}		if (tx_block == TX_BUF_START+((lp->num_tx_bufs-1)*TX_BUF_SIZE)) 			lp->tx_reap = tx_block = TX_BUF_START;		else			lp->tx_reap = tx_block += TX_BUF_SIZE;		dev->tbusy = 0;		mark_bh(NET_BH);	}	while (lp->tx_reap != lp->tx_head);	lp->tx_link = lp->tx_tail + 0x08;	outw(old_rp,ioaddr+READ_PTR);	outw(old_wp,ioaddr+WRITE_PTR);	return status;}/*  * This should never happen. It is called when some higher * routine detects the CU has stopped, to try to restart * it from the last packet we knew we were working on, * or the idle loop if we had finished for the time. */static void eexp_hw_txrestart(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	unsigned short ioaddr = dev->base_addr;  	lp->last_tx_restart = lp->tx_link;	outw(lp->tx_link,ioaddr+SCB_CBL);	outw(SCB_CUstart,ioaddr+SCB_CMD);	outw(0,ioaddr+SCB_STATUS);	outb(0,ioaddr+SIGNAL_CA);	{		unsigned short boguscount=50,failcount=5;		while (!inw(ioaddr+SCB_STATUS)) 		{			if (!--boguscount) 			{				if (--failcount) 				{					printk(KERN_WARNING "%s: CU start timed out, status %04x, cmd %04x\n",						dev->name, inw(ioaddr+SCB_STATUS), inw(ioaddr+SCB_CMD));					outw(lp->tx_link,ioaddr+SCB_CBL);					outw(0,ioaddr+SCB_STATUS);					outw(SCB_CUstart,ioaddr+SCB_CMD);					outb(0,ioaddr+SIGNAL_CA);					boguscount = 100;				}				else				{					printk(KERN_WARNING "%s: Failed to restart CU, resetting board...\n",dev->name);					eexp_hw_init586(dev);					dev->tbusy = 0;					mark_bh(NET_BH);					return;				}			}		}	}}/* * Writes down the list of transmit buffers into card * memory. Initial separate, repeated transmits link * them into a circular list, such that the CU can * be constantly active, and unlink them as we reap * transmitted packet buffers, so the CU doesn't loop * and endlessly transmit packets. (Try hacking the driver * to send continuous broadcast messages, say ARP requests * on a subnet with Windows boxes running on Novell and * LAN Workplace with EMM386. Amusing to watch them all die * horribly leaving the Linux boxes up!) */static void eexp_hw_txinit(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	unsigned short ioaddr = dev->base_addr;	unsigned short old_wp = inw(ioaddr+WRITE_PTR);	unsigned short tx_block = TX_BUF_START;	unsigned short curtbuf;	for ( curtbuf=0 ; curtbuf<lp->num_tx_bufs ; curtbuf++ ) 	{		outw(tx_block,ioaddr+WRITE_PTR);		outw(0x0000,ioaddr);		outw(Cmd_INT|Cmd_Xmit,ioaddr);		outw(tx_block+0x08,ioaddr);		outw(tx_block+0x0e,ioaddr);		outw(0x0000,ioaddr);		outw(0x0000,ioaddr);		outw(tx_block+0x08,ioaddr);		outw(0x8000,ioaddr);		outw(-1,ioaddr);		outw(tx_block+0x16,ioaddr);		outw(0x0000,ioaddr);		tx_block += TX_BUF_SIZE;	}	lp->tx_head = TX_BUF_START;	lp->tx_reap = TX_BUF_START;	lp->tx_tail = tx_block - TX_BUF_SIZE;	lp->tx_link = lp->tx_tail + 0x08;	lp->rx_buf_start = tx_block;	outw(old_wp,ioaddr+WRITE_PTR);}/* is this a standard test pattern, or dbecker randomness? */unsigned short rx_words[] = {	0xfeed,0xf00d,0xf001,0x0505,0x2424,0x6565,0xdeaf};/* * Write the circular list of receive buffer descriptors to * card memory. Note, we no longer mark the end of the list, * so if all the buffers fill up, the 82586 will loop until * we free one. This may sound dodgy, but it works, and * it makes the error detection in the interrupt handler * a lot simpler. */static void eexp_hw_rxinit(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	unsigned short ioaddr = dev->base_addr;	unsigned short old_wp = inw(ioaddr+WRITE_PTR);	unsigned short rx_block = lp->rx_buf_start;	lp->num_rx_bufs = 0;	lp->rx_first = rx_block;	do 	{		lp->num_rx_bufs++;		outw(rx_block,ioaddr+WRITE_PTR);		outw(0x0000,ioaddr);		outw(0x0000,ioaddr);		outw(rx_block+RX_BUF_SIZE,ioaddr);		outw(rx_block+0x16,ioaddr);		outsw(ioaddr, rx_words, sizeof(rx_words)>>1);		outw(0x8000,ioaddr);		outw(-1,ioaddr);		outw(rx_block+0x20,ioaddr);		outw(0x0000,ioaddr);		outw(0x8000|(RX_BUF_SIZE-0x20),ioaddr);		lp->rx_last = rx_block;		rx_block += RX_BUF_SIZE;	} while (rx_block <= lp->rx_buf_end-RX_BUF_SIZE);	outw(lp->rx_last+4,ioaddr+WRITE_PTR);	outw(lp->rx_first,ioaddr);	outw(old_wp,ioaddr+WRITE_PTR);}/* * Reset the 586, fill memory (including calls to * eexp_hw_[(rx)(tx)]init()) unreset, and start * the configuration sequence. We don't wait for this * to finish, but allow the interrupt handler to start * the CU and RU for us. We can't start the receive/ * transmission system up before we know that the * hardware is configured correctly */static void eexp_hw_init586(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	unsigned short ioaddr = dev->base_addr;#if NET_DEBUG > 6        printk("%s: eexp_hw_init586()\n", dev->name);#endif	lp->started = 0;	set_loopback;	outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);	outb_p(i586_RST,ioaddr+EEPROM_Ctrl);	udelay(2000);  /* delay 20ms */        {		unsigned long ofs;		for (ofs = 0; ofs < lp->rx_buf_end; ofs += 32) {			unsigned long i;			outw_p(ofs, ioaddr+SM_PTR);			for (i = 0; i < 16; i++) {				outw_p(0, ioaddr+SM_ADDR(i<<1));			}		}	}	outw_p(lp->rx_buf_end,ioaddr+WRITE_PTR);	start_code[28] = (dev->flags & IFF_PROMISC)?(start_code[28] | 1):(start_code[28] & ~1);	lp->promisc = dev->flags & IFF_PROMISC;	/* We may die here */	outsw(ioaddr, start_code, sizeof(start_code)>>1);	outw(CONF_HW_ADDR,ioaddr+WRITE_PTR);	outsw(ioaddr,dev->dev_addr,3);	eexp_hw_txinit(dev);	eexp_hw_rxinit(dev);	outw(0,ioaddr+WRITE_PTR);	outw(1,ioaddr);	outb(0,ioaddr+EEPROM_Ctrl);	outw(0,ioaddr+SCB_CMD);	outb(0,ioaddr+SIGNAL_CA);	{		unsigned short rboguscount=50,rfailcount=5;		while (outw(0,ioaddr+READ_PTR),inw(ioaddr)) 		{			if (!--rboguscount) 			{				printk(KERN_WARNING "%s: i82586 reset timed out, kicking...\n",					dev->name);				outw(0,ioaddr+SCB_CMD);				outb(0,ioaddr+SIGNAL_CA);				rboguscount = 100;				if (!--rfailcount) 				{					printk(KERN_WARNING "%s: i82586 not responding, giving up.\n",						dev->name);					return;				}			}		}	}	outw(CONF_LINK,ioaddr+SCB_CBL);	outw(0,ioaddr+SCB_STATUS);	outw(0xf000|SCB_CUstart,ioaddr+SCB_CMD);	outb(0,ioaddr+SIGNAL_CA);	{		unsigned short iboguscount=50,ifailcount=5;		while (!inw(ioaddr+SCB_STATUS)) 		{			if (!--iboguscount) 			{				if (--ifailcount) 				{					printk(KERN_WARNING "%s: i82586 initialization timed out, status %04x, cmd %04x\n",						dev->name, inw(ioaddr+SCB_STATUS), inw(ioaddr+SCB_CMD));					outw(CONF_LINK,ioaddr+SCB_CBL);					outw(0,ioaddr+SCB_STATUS);					outw(0xf000|SCB_CUstart,ioaddr+SCB_CMD);					outb(0,ioaddr+SIGNAL_CA);					iboguscount = 100;				}				else 				{					printk(KERN_WARNING "%s: Failed to initialize i82586, giving up.\n",dev->name);					return;				}			}		}	}  	outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ);	clear_loopback;	lp->init_time = jiffies;#if NET_DEBUG > 6        printk("%s: leaving eexp_hw_init586()\n", dev->name);#endif	return;}/*  * completely reset the EtherExpress hardware. We will most likely get * an interrupt during this whether we want one or not. It is best, * therefore, to call this while we don't have a request_irq() on. */static void eexp_hw_ASICrst(struct device *dev){	unsigned short ioaddr = dev->base_addr;	unsigned short wrval = 0x0001,succount=0,boguscount=500;	outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);	PRIV(dev)->started = 0;	outb(ASIC_RST|i586_RST,ioaddr+EEPROM_Ctrl);	while (succount<20) 	{		if (wrval == 0xffff) 			wrval = 0x0001;		outw(0,ioaddr+WRITE_PTR);		outw(wrval,ioaddr);		outw(0,ioaddr+READ_PTR);		if (wrval++ == inw(ioaddr)) 			succount++;		else 		{			succount = 0;			if (!boguscount--) 			{				boguscount = 500;				printk("%s: Having problems resetting EtherExpress ASIC, continuing...\n",					dev->name);				wrval = 0x0001;				outb(ASIC_RST|i586_RST,ioaddr+EEPROM_Ctrl);			}		}	}	outb(i586_RST,ioaddr+EEPROM_Ctrl);}/* * Set or clear the multicast filter for this adaptor. * We have to do a complete 586 restart for this to take effect. * At the moment only promiscuous mode is supported. */static voideexp_set_multicast(struct device *dev){	if ((dev->flags & IFF_PROMISC) != PRIV(dev)->promisc)		eexp_hw_init586(dev);}/* * MODULE stuff */#ifdef MODULE#define EEXP_MAX_CARDS     4    /* max number of cards to support */#define NAMELEN            8    /* max length of dev->name (inc null) */static char namelist[NAMELEN * EEXP_MAX_CARDS] = { 0, };static struct device dev_eexp[EEXP_MAX_CARDS] = {        { NULL,         /* will allocate dynamically */	  0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe },  };int irq[EEXP_MAX_CARDS] = {0, };int io[EEXP_MAX_CARDS] = {0, };/* Ideally the user would give us io=, irq= for every card.  If any parameters * are specified, we verify and then use them.  If no parameters are given, we * autoprobe for one card only. */int init_module(void){	int this_dev, found = 0;	for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {		struct device *dev = &dev_eexp[this_dev];		dev->name = namelist + (NAMELEN*this_dev);		dev->irq = irq[this_dev];		dev->base_addr = io[this_dev];		if (io[this_dev] == 0) {			if (this_dev) break;			printk(KERN_NOTICE "eexpress.c: Module autoprobe not recommended, give io=xx.\n");		}		if (register_netdev(dev) != 0) {			printk(KERN_WARNING "eexpress.c: Failed to register card at 0x%x.\n", io[this_dev]);			if (found != 0) return 0;			return -ENXIO;		}		found++;	}	return 0;}void cleanup_module(void){	int this_dev;        	for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {		struct device *dev = &dev_eexp[this_dev];		if (dev->priv != NULL) {			kfree(dev->priv);			dev->priv = NULL;			release_region(dev->base_addr, EEXP_IO_EXTENT);			unregister_netdev(dev);		}	}}#endif/* * Local Variables: *  c-file-style: "linux" *  tab-width: 8 *  compile-command: "gcc -D__KERNEL__ -I/discs/bibble/src/linux-1.3.69/include  -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce -pipe -m486 -DCPU=486 -DMODULE  -c 3c505.c" * End: */

⌨️ 快捷键说明

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