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

📄 ether3.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 2 页
字号:
	priv->regs.config1 &= ~CFG1_RECVPROMISC;	if (dev->flags & IFF_PROMISC) {		/* promiscuous mode */		priv->regs.config1 |= CFG1_RECVPROMISC;	} else if (dev->flags & IFF_ALLMULTI) {		priv->regs.config1 |= CFG1_RECVSPECBRMULTI;	} else		priv->regs.config1 |= CFG1_RECVSPECBROAD;	ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);}static voidether3_timeout(struct net_device *dev){	struct dev_priv *priv = (struct dev_priv *)dev->priv;	unsigned long flags;	del_timer(&priv->timer);	save_flags_cli(flags);	printk(KERN_ERR "%s: transmit timed out, network cable problem?\n", dev->name);	printk(KERN_ERR "%s: state: { status=%04X cfg1=%04X cfg2=%04X }\n", dev->name,		ether3_inw(REG_STATUS), ether3_inw(REG_CONFIG1), ether3_inw(REG_CONFIG2));	printk(KERN_ERR "%s: { rpr=%04X rea=%04X tpr=%04X }\n", dev->name,		ether3_inw(REG_RECVPTR), ether3_inw(REG_RECVEND), ether3_inw(REG_TRANSMITPTR));	printk(KERN_ERR "%s: tx head=%X tx tail=%X\n", dev->name,		priv->tx_head, priv->tx_tail);	ether3_setbuffer(dev, buffer_read, priv->tx_tail);	printk(KERN_ERR "%s: packet status = %08X\n", dev->name, ether3_readlong(dev));	restore_flags(flags);	priv->regs.config2 |= CFG2_CTRLO;	priv->stats.tx_errors += 1;	ether3_outw(priv->regs.config2, REG_CONFIG2);	priv->tx_head = priv->tx_tail = 0;	netif_wake_queue(dev);}/* * Transmit a packet */static intether3_sendpacket(struct sk_buff *skb, struct net_device *dev){	struct dev_priv *priv = (struct dev_priv *)dev->priv;	unsigned long flags;	unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;	unsigned int ptr, next_ptr;	length = (length + 1) & ~1;	if (priv->broken) {		dev_kfree_skb(skb);		priv->stats.tx_dropped ++;		netif_start_queue(dev);		return 0;	}	next_ptr = (priv->tx_head + 1) & 15;	save_flags_cli(flags);	if (priv->tx_tail == next_ptr) {		restore_flags(flags);		return 1;	/* unable to queue */	}	dev->trans_start = jiffies;	ptr		 = 0x600 * priv->tx_head;	priv->tx_head	 = next_ptr;	next_ptr	*= 0x600;#define TXHDR_FLAGS (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE|TXHDR_DATAFOLLOWS|TXHDR_ENSUCCESS)	ether3_setbuffer(dev, buffer_write, next_ptr);	ether3_writelong(dev, 0);	ether3_setbuffer(dev, buffer_write, ptr);	ether3_writelong(dev, 0);	ether3_writebuffer(dev, skb->data, length);	ether3_writeword(dev, htons(next_ptr));	ether3_writeword(dev, TXHDR_CHAINCONTINUE >> 16);	ether3_setbuffer(dev, buffer_write, ptr);	ether3_writeword(dev, htons((ptr + length + 4)));	ether3_writeword(dev, TXHDR_FLAGS >> 16);	ether3_ledon(dev, priv);	if (!(ether3_inw(REG_STATUS) & STAT_TXON)) {		ether3_outw(ptr, REG_TRANSMITPTR);		ether3_outw(priv->regs.command | CMD_TXON, REG_COMMAND);	}	next_ptr = (priv->tx_head + 1) & 15;	restore_flags(flags);	dev_kfree_skb(skb);	if (priv->tx_tail == next_ptr)		netif_stop_queue(dev);	return 0;}static voidether3_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = (struct net_device *)dev_id;	struct dev_priv *priv;	unsigned int status;#if NET_DEBUG > 1	if(net_debug & DEBUG_INT)		printk("eth3irq: %d ", irq);#endif	priv = (struct dev_priv *)dev->priv;	status = ether3_inw(REG_STATUS);	if (status & STAT_INTRX) {		ether3_outw(CMD_ACKINTRX | priv->regs.command, REG_COMMAND);		ether3_rx(dev, priv, 12);	}	if (status & STAT_INTTX) {		ether3_outw(CMD_ACKINTTX | priv->regs.command, REG_COMMAND);		ether3_tx(dev, priv);	}#if NET_DEBUG > 1	if(net_debug & DEBUG_INT)		printk("done\n");#endif}/* * If we have a good packet(s), get it/them out of the buffers. */static intether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt){	unsigned int next_ptr = priv->rx_head, received = 0;	ether3_ledon(dev, priv);	do {		unsigned int this_ptr, status;		unsigned char addrs[16];		/*		 * read the first 16 bytes from the buffer.		 * This contains the status bytes etc and ethernet addresses,		 * and we also check the source ethernet address to see if		 * it originated from us.		 */		{			unsigned int temp_ptr;			ether3_setbuffer(dev, buffer_read, next_ptr);			temp_ptr = ether3_readword(dev);			status = ether3_readword(dev);			if ((status & (RXSTAT_DONE | RXHDR_CHAINCONTINUE | RXHDR_RECEIVE)) !=				(RXSTAT_DONE | RXHDR_CHAINCONTINUE) || !temp_ptr)				break;			this_ptr = next_ptr + 4;			next_ptr = ntohs(temp_ptr);		}		ether3_setbuffer(dev, buffer_read, this_ptr);		ether3_readbuffer(dev, addrs+2, 12);if (next_ptr < RX_START || next_ptr >= RX_END) { int i; printk("%s: bad next pointer @%04X: ", dev->name, priv->rx_head); printk("%02X %02X %02X %02X ", next_ptr >> 8, next_ptr & 255, status & 255, status >> 8); for (i = 2; i < 14; i++)   printk("%02X ", addrs[i]); printk("\n"); next_ptr = priv->rx_head; break;}		/* 		 * ignore our own packets...	 	 */		if (!(*(unsigned long *)&dev->dev_addr[0] ^ *(unsigned long *)&addrs[2+6]) &&		    !(*(unsigned short *)&dev->dev_addr[4] ^ *(unsigned short *)&addrs[2+10])) {			maxcnt ++; /* compensate for loopedback packet */			ether3_outw(next_ptr >> 8, REG_RECVEND);		} else		if (!(status & (RXSTAT_OVERSIZE|RXSTAT_CRCERROR|RXSTAT_DRIBBLEERROR|RXSTAT_SHORTPACKET))) {			unsigned int length = next_ptr - this_ptr;			struct sk_buff *skb;			if (next_ptr <= this_ptr)				length += RX_END - RX_START;			skb = dev_alloc_skb(length + 2);			if (skb) {				unsigned char *buf;				skb->dev = dev;				skb_reserve(skb, 2);				buf = skb_put(skb, length);				ether3_readbuffer(dev, buf + 12, length - 12);				ether3_outw(next_ptr >> 8, REG_RECVEND);				*(unsigned short *)(buf + 0)	= *(unsigned short *)(addrs + 2);				*(unsigned long *)(buf + 2)	= *(unsigned long *)(addrs + 4);				*(unsigned long *)(buf + 6)	= *(unsigned long *)(addrs + 8);				*(unsigned short *)(buf + 10)	= *(unsigned short *)(addrs + 12);				skb->protocol = eth_type_trans(skb, dev);				netif_rx(skb);				received ++;			} else				goto dropping;		} else {			struct net_device_stats *stats = &priv->stats;			ether3_outw(next_ptr >> 8, REG_RECVEND);			if (status & RXSTAT_OVERSIZE)	  stats->rx_over_errors ++;			if (status & RXSTAT_CRCERROR)	  stats->rx_crc_errors ++;			if (status & RXSTAT_DRIBBLEERROR) stats->rx_fifo_errors ++;			if (status & RXSTAT_SHORTPACKET)  stats->rx_length_errors ++;			stats->rx_errors++;		}	}	while (-- maxcnt);done:	priv->stats.rx_packets += received;	priv->rx_head = next_ptr;	/*	 * If rx went off line, then that means that the buffer may be full.  We	 * have dropped at least one packet.	 */	if (!(ether3_inw(REG_STATUS) & STAT_RXON)) {		priv->stats.rx_dropped ++;    		ether3_outw(next_ptr, REG_RECVPTR);		ether3_outw(priv->regs.command | CMD_RXON, REG_COMMAND);	}	return maxcnt;dropping:{	static unsigned long last_warned;	ether3_outw(next_ptr >> 8, REG_RECVEND);	/*	 * Don't print this message too many times...	 */	if (jiffies - last_warned > 30 * HZ) {		last_warned = jiffies;		printk("%s: memory squeeze, dropping packet.\n", dev->name);	}	priv->stats.rx_dropped ++;	goto done;	}}/* * Update stats for the transmitted packet(s) */static voidether3_tx(struct net_device *dev, struct dev_priv *priv){	unsigned int tx_tail = priv->tx_tail;	int max_work = 14;	do {	    	unsigned long status;    		/*	    	 * Read the packet header    		 */	    	ether3_setbuffer(dev, buffer_read, tx_tail * 0x600);    		status = ether3_readlong(dev);		/*		 * Check to see if this packet has been transmitted		 */		if ((status & (TXSTAT_DONE | TXHDR_TRANSMIT)) !=		    (TXSTAT_DONE | TXHDR_TRANSMIT))			break;		/*		 * Update errors		 */		if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS)))			priv->stats.tx_packets++;		else {			priv->stats.tx_errors ++;			if (status & TXSTAT_16COLLISIONS) priv->stats.collisions += 16;			if (status & TXSTAT_BABBLED) priv->stats.tx_fifo_errors ++;		}		tx_tail = (tx_tail + 1) & 15;	} while (--max_work);	if (priv->tx_tail != tx_tail) {		priv->tx_tail = tx_tail;		netif_wake_queue(dev);	}}static void __init ether3_banner(void){	static unsigned version_printed = 0;	if (net_debug && version_printed++ == 0)		printk(KERN_INFO "%s", version);}static const char * __initether3_get_dev(struct net_device *dev, struct expansion_card *ec){	const char *name = "ether3";	dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);	dev->irq = ec->irq;	if (ec->cid.manufacturer == MANU_ANT &&	    ec->cid.product == PROD_ANT_ETHERB) {		dev->base_addr += 0x200;		name = "etherb";	}	ec->irqaddr = (volatile unsigned char *)ioaddr(dev->base_addr);	ec->irqmask = 0xf0;	if (ether3_addr(dev->dev_addr, ec))		name = NULL;	return name;}static struct net_device * __init ether3_init_one(struct expansion_card *ec){	struct net_device *dev;	struct dev_priv *priv;	const char *name;	int i, bus_type;	ether3_banner();	ecard_claim(ec);	dev = init_etherdev(NULL, sizeof(struct dev_priv));	if (!dev)		goto out;	SET_MODULE_OWNER(dev);	name = ether3_get_dev(dev, ec);	if (!name)		goto free;	/*	 * this will not fail - the nature of the bus ensures this	 */	if (!request_region(dev->base_addr, 128, dev->name))		goto free;	priv = (struct dev_priv *) dev->priv;	/* Reset card...	 */	ether3_outb(0x80, REG_CONFIG2 + 1);	bus_type = BUS_UNKNOWN;	udelay(4);	/* Test using Receive Pointer (16-bit register) to find out	 * how the ether3 is connected to the bus...	 */	if (ether3_probe_bus_8(dev, 0x100) &&	    ether3_probe_bus_8(dev, 0x201))		bus_type = BUS_8;	if (bus_type == BUS_UNKNOWN &&	    ether3_probe_bus_16(dev, 0x101) &&	    ether3_probe_bus_16(dev, 0x201))		bus_type = BUS_16;	switch (bus_type) {	case BUS_UNKNOWN:		printk(KERN_ERR "%s: unable to identify bus width\n", dev->name);		goto failed;	case BUS_8:		printk(KERN_ERR "%s: %s found, but is an unsupported "			"8-bit card\n", dev->name, name);		goto failed;	default:		break;	}	printk("%s: %s in slot %d, ", dev->name, name, ec->slot_no);	for (i = 0; i < 6; i++)		printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');	if (ether3_init_2(dev))		goto failed;	dev->open		= ether3_open;	dev->stop		= ether3_close;	dev->hard_start_xmit	= ether3_sendpacket;	dev->get_stats		= ether3_getstats;	dev->set_multicast_list	= ether3_setmulticastlist;	dev->tx_timeout		= ether3_timeout;	dev->watchdog_timeo	= 5 * HZ / 100;	return 0;failed:	release_region(dev->base_addr, 128);free:	unregister_netdev(dev);	kfree(dev);out:	ecard_release(ec);	return NULL;}static struct expansion_card	*e_card[MAX_ECARDS];static struct net_device	*e_dev[MAX_ECARDS];static int ether3_init(void){	int i, ret = -ENODEV;	ecard_startfind();	for (i = 0; i < MAX_ECARDS; i++) {		struct net_device *dev;		struct expansion_card *ec;		ec = ecard_find(0, ether3_cids);		if (!ec)			break;		dev = ether3_init_one(ec);		if (!dev)			break;		e_card[i] = ec;		e_dev[i]  = dev;		ret = 0;	}	return ret;}static void ether3_exit(void){	int i;	for (i = 0; i < MAX_ECARDS; i++) {		if (e_dev[i]) {			unregister_netdev(e_dev[i]);			release_region(e_dev[i]->base_addr, 128);			kfree(e_dev[i]);			e_dev[i] = NULL;		}		if (e_card[i]) {			ecard_release(e_card[i]);			e_card[i] = NULL;		}	}}module_init(ether3_init);module_exit(ether3_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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