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

📄 ether3.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI;	} else		priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD;	ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);}static void ether3_timeout(struct net_device *dev){	unsigned long flags;	del_timer(&priv(dev)->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(dev)->tx_head, priv(dev)->tx_tail);	ether3_setbuffer(dev, buffer_read, priv(dev)->tx_tail);	printk(KERN_ERR "%s: packet status = %08X\n", dev->name, ether3_readlong(dev));	local_irq_restore(flags);	priv(dev)->regs.config2 |= CFG2_CTRLO;	priv(dev)->stats.tx_errors += 1;	ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);	priv(dev)->tx_head = priv(dev)->tx_tail = 0;	netif_wake_queue(dev);}/* * Transmit a packet */static intether3_sendpacket(struct sk_buff *skb, struct net_device *dev){	unsigned long flags;	unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;	unsigned int ptr, next_ptr;	if (priv(dev)->broken) {		dev_kfree_skb(skb);		priv(dev)->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(dev)->tx_head + 1) & 15;	local_irq_save(flags);	if (priv(dev)->tx_tail == next_ptr) {		local_irq_restore(flags);		return 1;	/* unable to queue */	}	dev->trans_start = jiffies;	ptr		 = 0x600 * priv(dev)->tx_head;	priv(dev)->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);	if (!(ether3_inw(REG_STATUS) & STAT_TXON)) {		ether3_outw(ptr, REG_TRANSMITPTR);		ether3_outw(priv(dev)->regs.command | CMD_TXON, REG_COMMAND);	}	next_ptr = (priv(dev)->tx_head + 1) & 15;	local_irq_restore(flags);	dev_kfree_skb(skb);	if (priv(dev)->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;	unsigned int status, handled = IRQ_NONE;#if NET_DEBUG > 1	if(net_debug & DEBUG_INT)		printk("eth3irq: %d ", irq);#endif	status = ether3_inw(REG_STATUS);	if (status & STAT_INTRX) {		ether3_outw(CMD_ACKINTRX | priv(dev)->regs.command, REG_COMMAND);		ether3_rx(dev, 12);		handled = IRQ_HANDLED;	}	if (status & STAT_INTTX) {		ether3_outw(CMD_ACKINTTX | priv(dev)->regs.command, REG_COMMAND);		ether3_tx(dev);		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 int ether3_rx(struct net_device *dev, unsigned int maxcnt){	unsigned int next_ptr = priv(dev)->rx_head, received = 0;	ether3_ledon(dev);	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(dev)->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(dev)->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(dev)->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(dev)->stats.rx_packets += received;	priv(dev)->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(dev)->stats.rx_dropped ++;    		ether3_outw(next_ptr, REG_RECVPTR);		ether3_outw(priv(dev)->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(dev)->stats.rx_dropped ++;	goto done;	}}/* * Update stats for the transmitted packet(s) */static void ether3_tx(struct net_device *dev){	unsigned int tx_tail = priv(dev)->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(dev)->stats.tx_packets++;		else {			priv(dev)->stats.tx_errors ++;			if (status & TXSTAT_16COLLISIONS)				priv(dev)->stats.collisions += 16;			if (status & TXSTAT_BABBLED)				priv(dev)->stats.tx_fifo_errors ++;		}		tx_tail = (tx_tail + 1) & 15;	} while (--max_work);	if (priv(dev)->tx_tail != tx_tail) {		priv(dev)->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 int __devinitether3_probe(struct expansion_card *ec, const struct ecard_id *id){	const struct ether3_data *data = id->data;	struct net_device *dev;	int i, bus_type, ret;	ether3_banner();	ret = ecard_request_resources(ec);	if (ret)		goto out;	dev = alloc_etherdev(sizeof(struct dev_priv));	if (!dev) {		ret = -ENOMEM;		goto release;	}	SET_MODULE_OWNER(dev);	SET_NETDEV_DEV(dev, &ec->dev);	priv(dev)->base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),				  ecard_resource_len(ec, ECARD_RES_MEMC));	if (!priv(dev)->base) {		ret = -ENOMEM;		goto free;	}	ec->irqaddr = priv(dev)->base + data->base_offset;	ec->irqmask = 0xf0;	priv(dev)->seeq = priv(dev)->base + data->base_offset;	dev->irq = ec->irq;	ether3_addr(dev->dev_addr, ec);	init_timer(&priv(dev)->timer);	/* Reset card...	 */	ether3_outb(0x80, REG_CONFIG2 + 4);	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 free;	case BUS_8:		printk(KERN_ERR "%s: %s found, but is an unsupported "			"8-bit card\n", dev->name, data->name);		ret = -ENODEV;		goto free;	default:		break;	}	if (ether3_init_2(dev)) {		ret = -ENODEV;		goto free;	}	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 free;	printk("%s: %s in slot %d, ", dev->name, data->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; free:	if (priv(dev)->base)		iounmap(priv(dev)->base);	free_netdev(dev); release:	ecard_release_resources(ec); 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);	iounmap(priv(dev)->base);	free_netdev(dev);	ecard_release_resources(ec);}static struct ether3_data ether3 = {	.name		= "ether3",	.base_offset	= 0,};static struct ether3_data etherb = {	.name		= "etherb",	.base_offset	= 0x800,};static const struct ecard_id ether3_ids[] = {	{ MANU_ANT2, PROD_ANT_ETHER3, &ether3 },	{ MANU_ANT,  PROD_ANT_ETHER3, &ether3 },	{ MANU_ANT,  PROD_ANT_ETHERB, &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 + -