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

📄 eexpress.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
		outb(wval,ioaddr+EEPROM_Ctrl);		outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl);		eeprom_delay();		outb(wval,ioaddr+EEPROM_Ctrl);		eeprom_delay();	}	wval &= ~EC_Wr;	outb(wval,ioaddr+EEPROM_Ctrl);	for (i=0x8000 ; i ; i>>=1 )	{		outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl);		eeprom_delay();		if (inb(ioaddr+EEPROM_Ctrl)&EC_Rd)			rval |= i;		outb(wval,ioaddr+EEPROM_Ctrl);		eeprom_delay();	}	wval &= ~EC_CS;	outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl);	eeprom_delay();	outb(wval,ioaddr+EEPROM_Ctrl);	eeprom_delay();	return rval;}/* * Reap tx buffers and return last transmit status. * if ==0 then either: *    a) we're not transmitting anything, so why are we here? *    b) we've died. * otherwise, Stat_Busy(return) means we've still got some packets * to transmit, Stat_Done(return) means our buffers should be empty * again */static unsigned short eexp_hw_lasttxstat(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	unsigned short tx_block = lp->tx_reap;	unsigned short status;	if ((!dev->tbusy) && lp->tx_head==lp->tx_reap)		return 0x0000;	do	{		outw(tx_block & ~31, dev->base_addr + SM_PTR);		status = inw(dev->base_addr + SHADOW(tx_block));		if (!Stat_Done(status))		{			lp->tx_link = tx_block;			return status;		}		else		{			lp->last_tx_restart = 0;			lp->stats.collisions += Stat_NoColl(status);			if (!Stat_OK(status))			{				char *whatsup = NULL;				lp->stats.tx_errors++;  				if (Stat_Abort(status))   					lp->stats.tx_aborted_errors++;				if (Stat_TNoCar(status)) {					whatsup = "aborted, no carrier";					lp->stats.tx_carrier_errors++;				}				if (Stat_TNoCTS(status)) {					whatsup = "aborted, lost CTS";  					lp->stats.tx_carrier_errors++;				}				if (Stat_TNoDMA(status)) {					whatsup = "FIFO underran";  					lp->stats.tx_fifo_errors++;				}				if (Stat_TXColl(status)) {					whatsup = "aborted, too many collisions";					lp->stats.tx_aborted_errors++;				}				if (whatsup)					printk(KERN_INFO "%s: transmit %s\n",					       dev->name, whatsup);			}			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;	return status;}/* * This should never happen. It is called when some higher routine detects * that 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;	scb_wrcbl(dev, lp->tx_link);	scb_command(dev, SCB_CUstart);	outb(0,ioaddr+SIGNAL_CA);	{		unsigned short boguscount=50,failcount=5;		while (!scb_status(dev))		{			if (!--boguscount)			{				if (--failcount)				{					printk(KERN_WARNING "%s: CU start timed out, status %04x, cmd %04x\n", dev->name, scb_status(dev), scb_rdcmd(dev));				        scb_wrcbl(dev, lp->tx_link);					scb_command(dev, SCB_CUstart);					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.  Each * entry consists of an 82586 transmit command, followed by a jump * pointing to itself.  When we want to transmit a packet, we write * the data into the appropriate transmit buffer and then modify the * preceding jump to point at the new transmit command.  This means that * the 586 command unit is continuously active. */static void eexp_hw_txinit(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	unsigned short tx_block = TX_BUF_START;	unsigned short curtbuf;	unsigned short ioaddr = dev->base_addr;	for ( curtbuf=0 ; curtbuf<lp->num_tx_bufs ; curtbuf++ )	{		outw(tx_block, ioaddr + WRITE_PTR);	        outw(0x0000, ioaddr + DATAPORT);		outw(Cmd_INT|Cmd_Xmit, ioaddr + DATAPORT);		outw(tx_block+0x08, ioaddr + DATAPORT);		outw(tx_block+0x0e, ioaddr + DATAPORT);		outw(0x0000, ioaddr + DATAPORT);		outw(0x0000, ioaddr + DATAPORT);		outw(tx_block+0x08, ioaddr + DATAPORT);		outw(0x8000, ioaddr + DATAPORT);		outw(-1, ioaddr + DATAPORT);		outw(tx_block+0x16, ioaddr + DATAPORT);		outw(0x0000, ioaddr + DATAPORT);		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;}/* * Write the circular list of receive buffer descriptors to card memory. * The end of the list isn't marked, which means that the 82586 receive * unit will loop until buffers become available (this avoids it giving us * "out of resources" messages). */static void eexp_hw_rxinit(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	unsigned short rx_block = lp->rx_buf_start;	unsigned short ioaddr = dev->base_addr;	lp->num_rx_bufs = 0;	lp->rx_first = lp->rx_ptr = rx_block;	do	{		lp->num_rx_bufs++;		outw(rx_block, ioaddr + WRITE_PTR);		outw(0, ioaddr + DATAPORT);  outw(0, ioaddr+DATAPORT);		outw(rx_block + RX_BUF_SIZE, ioaddr+DATAPORT);		outw(0xffff, ioaddr+DATAPORT);		outw(0x0000, ioaddr+DATAPORT);		outw(0xdead, ioaddr+DATAPORT);		outw(0xdead, ioaddr+DATAPORT);		outw(0xdead, ioaddr+DATAPORT);		outw(0xdead, ioaddr+DATAPORT);		outw(0xdead, ioaddr+DATAPORT);		outw(0xdead, ioaddr+DATAPORT);		outw(0x0000, ioaddr+DATAPORT);		outw(rx_block + RX_BUF_SIZE + 0x16, ioaddr+DATAPORT);		outw(rx_block + 0x20, ioaddr+DATAPORT);		outw(0, ioaddr+DATAPORT);		outw(RX_BUF_SIZE-0x20, ioaddr+DATAPORT);		lp->rx_last = rx_block;		rx_block += RX_BUF_SIZE;	} while (rx_block <= lp->rx_buf_end-RX_BUF_SIZE);	/* Make first Rx frame descriptor point to first Rx buffer           descriptor */	outw(lp->rx_first + 6, ioaddr+WRITE_PTR);	outw(lp->rx_first + 0x16, ioaddr+DATAPORT);	/* Close Rx frame descriptor ring */  	outw(lp->rx_last + 4, ioaddr+WRITE_PTR);  	outw(lp->rx_first, ioaddr+DATAPORT);  	/* Close Rx buffer descriptor ring */	outw(lp->rx_last + 0x16 + 2, ioaddr+WRITE_PTR);	outw(lp->rx_first + 0x16, ioaddr+DATAPORT);	}/* * Un-reset the 586, 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;	int i;#if NET_DEBUG > 6	printk("%s: eexp_hw_init586()\n", dev->name);#endif	lp->started = 0;	set_loopback(dev);	outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);	/* Download the startup code */	outw(lp->rx_buf_end & ~31, ioaddr + SM_PTR);	outw(lp->width?0x0001:0x0000, ioaddr + 0x8006);	outw(0x0000, ioaddr + 0x8008);	outw(0x0000, ioaddr + 0x800a);	outw(0x0000, ioaddr + 0x800c);	outw(0x0000, ioaddr + 0x800e);	for (i = 0; i < (sizeof(start_code)); i+=32) {		int j;		outw(i, ioaddr + SM_PTR);		for (j = 0; j < 16; j+=2)			outw(start_code[(i+j)/2],			     ioaddr+0x4000+j);		for (j = 0; j < 16; j+=2)			outw(start_code[(i+j+16)/2],			     ioaddr+0x8000+j);	}	/* Do we want promiscuous mode or multicast? */	outw(CONF_PROMISC & ~31, ioaddr+SM_PTR);	i = inw(ioaddr+SHADOW(CONF_PROMISC));	outw((dev->flags & IFF_PROMISC)?(i|1):(i & ~1), 	     ioaddr+SHADOW(CONF_PROMISC));	lp->was_promisc = dev->flags & IFF_PROMISC;#if 0	eexp_setup_filter(dev);#endif	/* Write our hardware address */	outw(CONF_HWADDR & ~31, ioaddr+SM_PTR);	outw(((unsigned short *)dev->dev_addr)[0], ioaddr+SHADOW(CONF_HWADDR));	outw(((unsigned short *)dev->dev_addr)[1], 	     ioaddr+SHADOW(CONF_HWADDR+2));	outw(((unsigned short *)dev->dev_addr)[2],	     ioaddr+SHADOW(CONF_HWADDR+4));	eexp_hw_txinit(dev);	eexp_hw_rxinit(dev);	outb(0,ioaddr+EEPROM_Ctrl);	mdelay(5);	scb_command(dev, 0xf000);	outb(0,ioaddr+SIGNAL_CA);	outw(0, ioaddr+SM_PTR);	{		unsigned short rboguscount=50,rfailcount=5;		while (inw(ioaddr+0x4000))		{			if (!--rboguscount)			{				printk(KERN_WARNING "%s: i82586 reset timed out, kicking...\n",					dev->name);				scb_command(dev, 0);				outb(0,ioaddr+SIGNAL_CA);				rboguscount = 100;				if (!--rfailcount)				{					printk(KERN_WARNING "%s: i82586 not responding, giving up.\n",						dev->name);					return;				}			}		}	}        scb_wrcbl(dev, CONF_LINK);	scb_command(dev, 0xf000|SCB_CUstart);	outb(0,ioaddr+SIGNAL_CA);	{		unsigned short iboguscount=50,ifailcount=5;		while (!scb_status(dev))		{			if (!--iboguscount)			{				if (--ifailcount)				{					printk(KERN_WARNING "%s: i82586 initialization timed out, status %04x, cmd %04x\n",						dev->name, scb_status(dev), scb_rdcmd(dev));					scb_wrcbl(dev, CONF_LINK);				        scb_command(dev, 0xf000|SCB_CUstart);					outb(0,ioaddr+SIGNAL_CA);					iboguscount = 100;				}				else				{					printk(KERN_WARNING "%s: Failed to initialize i82586, giving up.\n",dev->name);					return;				}			}		}	}	clear_loopback(dev);	outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ);	lp->init_time = jiffies;#if NET_DEBUG > 6        printk("%s: leaving eexp_hw_init586()\n", dev->name);#endif	return;}static void eexp_setup_filter(struct device *dev){	struct dev_mc_list *dmi = dev->mc_list;	unsigned short ioaddr = dev->base_addr;	int count = dev->mc_count;	int i;	if (count > 8) {		printk(KERN_INFO "%s: too many multicast addresses (%d)\n",		       dev->name, count);		count = 8;	}		outw(CONF_NR_MULTICAST & ~31, ioaddr+SM_PTR);	outw(count, ioaddr+SHADOW(CONF_NR_MULTICAST));	for (i = 0; i < count; i++) {		unsigned short *data = (unsigned short *)dmi->dmi_addr;		if (!dmi) {			printk(KERN_INFO "%s: too few multicast addresses\n", dev->name);			break;		}		if (dmi->dmi_addrlen != ETH_ALEN) {			printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name);			continue;		}		outw((CONF_MULTICAST+(6*i)) & ~31, ioaddr+SM_PTR);		outw(data[0], ioaddr+SHADOW(CONF_MULTICAST+(6*i)));		outw((CONF_MULTICAST+(6*i)+2) & ~31, ioaddr+SM_PTR);		outw(data[1], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+2));		outw((CONF_MULTICAST+(6*i)+4) & ~31, ioaddr+SM_PTR);		outw(data[2], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+4));	}}/* * Set or clear the multicast filter for this adaptor. */static voideexp_set_multicast(struct device *dev){        unsigned short ioaddr = dev->base_addr;        struct net_local *lp = (struct net_local *)dev->priv;        int kick = 0, i;        if ((dev->flags & IFF_PROMISC) != lp->was_promisc) {                outw(CONF_PROMISC & ~31, ioaddr+SM_PTR);                i = inw(ioaddr+SHADOW(CONF_PROMISC));                outw((dev->flags & IFF_PROMISC)?(i|1):(i & ~1),                     ioaddr+SHADOW(CONF_PROMISC));                lp->was_promisc = dev->flags & IFF_PROMISC;                kick = 1;        }        if (!(dev->flags & IFF_PROMISC)) {                eexp_setup_filter(dev);                if (lp->old_mc_count != dev->mc_count) {                        kick = 1;                        lp->old_mc_count = dev->mc_count;                }        }        if (kick) {                unsigned long oj;                scb_command(dev, SCB_CUsuspend);                outb(0, ioaddr+SIGNAL_CA);                outb(0, ioaddr+SIGNAL_CA);#if 0                printk("%s: waiting for CU to go suspended\n", dev->name);#endif                oj = jiffies;                while ((SCB_CUstat(scb_status(dev)) == 2) &&                       ((jiffies-oj) < 2000));		if (SCB_CUstat(scb_status(dev)) == 2)			printk("%s: warning, CU didn't stop\n", dev->name);                lp->started &= ~(STARTED_CU);                scb_wrcbl(dev, CONF_LINK);                scb_command(dev, SCB_CUstart);                outb(0, ioaddr+SIGNAL_CA);        }}/* * 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 },};static int irq[EEXP_MAX_CARDS] = {0, };static int io[EEXP_MAX_CARDS] = {0, };MODULE_PARM(io, "1-" __MODULE_STRING(EEXP_MAX_CARDS) "i");MODULE_PARM(irq, "1-" __MODULE_STRING(EEXP_MAX_CARDS) "i");/* 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) {			unregister_netdev(dev);			kfree(dev->priv);			dev->priv = NULL;			release_region(dev->base_addr, EEXP_IO_EXTENT);		}	}}#endif/* * Local Variables: *  c-file-style: "linux" *  tab-width: 8 * End: */

⌨️ 快捷键说明

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