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

📄 ether3.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
		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 = netdev_priv(dev);	unsigned long flags;	del_timer(&priv->timer);	local_irq_save(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));	local_irq_restore(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 = netdev_priv(dev);	unsigned long flags;	unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;	unsigned int ptr, next_ptr;	if (priv->broken) {		dev_kfree_skb(skb);		priv->stats.tx_dropped ++;		netif_start_queue(dev);		return 0;	}	length = (length + 1) & ~1;	if (length != skb->len) {		skb = skb_padto(skb, length);		if (skb == NULL)			goto out;	}	next_ptr = (priv->tx_head + 1) & 15;	local_irq_save(flags);	if (priv->tx_tail == next_ptr) {		local_irq_restore(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;	local_irq_restore(flags);	dev_kfree_skb(skb);	if (priv->tx_tail == next_ptr)		netif_stop_queue(dev); out:	return 0;}static irqreturn_tether3_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, handled = IRQ_NONE;#if NET_DEBUG > 1	if(net_debug & DEBUG_INT)		printk("eth3irq: %d ", irq);#endif	priv = netdev_priv(dev);	status = ether3_inw(REG_STATUS);	if (status & STAT_INTRX) {		ether3_outw(CMD_ACKINTRX | priv->regs.command, REG_COMMAND);		ether3_rx(dev, priv, 12);		handled = IRQ_HANDLED;	}	if (status & STAT_INTTX) {		ether3_outw(CMD_ACKINTTX | priv->regs.command, REG_COMMAND);		ether3_tx(dev, priv);		handled = IRQ_HANDLED;	}#if NET_DEBUG > 1	if(net_debug & DEBUG_INT)		printk("done\n");#endif	return handled;}/* * 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 (time_after(jiffies, last_warned + 10 * 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;	ether3_addr(dev->dev_addr, ec);	return name;}static int __devinitether3_probe(struct expansion_card *ec, const struct ecard_id *id){	struct net_device *dev;	struct dev_priv *priv;	const char *name;	int i, bus_type, ret;	ether3_banner();	dev = alloc_etherdev(sizeof(struct dev_priv));	if (!dev) {		ret = -ENOMEM;		goto out;	}	SET_MODULE_OWNER(dev);	name = ether3_get_dev(dev, ec);	if (!name) {		ret = -ENODEV;		goto free;	}	/*	 * this will not fail - the nature of the bus ensures this	 */	if (!request_region(dev->base_addr, 128, dev->name)) {		ret = -EBUSY;		goto free;	}	priv = netdev_priv(dev);	init_timer(&priv->timer);	/* 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);		ret = -ENODEV;		goto failed;	case BUS_8:		printk(KERN_ERR "%s: %s found, but is an unsupported "			"8-bit card\n", dev->name, name);		ret = -ENODEV;		goto failed;	default:		break;	}	if (ether3_init_2(dev)) {		ret = -ENODEV;		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;	ret = register_netdev(dev);	if (ret)		goto failed;	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' : ':');	ecard_set_drvdata(ec, dev);	return 0;failed:	release_region(dev->base_addr, 128);free:	free_netdev(dev);out:	return ret;}static void __devexit ether3_remove(struct expansion_card *ec){	struct net_device *dev = ecard_get_drvdata(ec);	ecard_set_drvdata(ec, NULL);	unregister_netdev(dev);	release_region(dev->base_addr, 128);	free_netdev(dev);}static const struct ecard_id ether3_ids[] = {	{ MANU_ANT2, PROD_ANT_ETHER3 },	{ MANU_ANT,  PROD_ANT_ETHER3 },	{ MANU_ANT,  PROD_ANT_ETHERB },	{ 0xffff, 0xffff }};static struct ecard_driver ether3_driver = {	.probe		= ether3_probe,	.remove		= __devexit_p(ether3_remove),	.id_table	= ether3_ids,	.drv = {		.name	= "ether3",	},};static int __init ether3_init(void){	return ecard_register_driver(&ether3_driver);}static void __exit ether3_exit(void){	ecard_remove_driver(&ether3_driver);}module_init(ether3_init);module_exit(ether3_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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