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

📄 ether3.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
ether3_probe(struct device *dev){	struct expansion_card *ec;	if (!dev)		return ENODEV;	ecard_startfind();	if ((ec = ecard_find(0, ether3_cids)) == NULL)		return ENODEV;	ether3_get_dev(dev, ec);	return ether3_probe1(dev);}#endif/* * Open/initialize the board.  This is called (in the current kernel) * sometime after booting when the 'ifconfig' program is run. * * This routine should set everything up anew at each open, even * registers that "should" only need to be set once at boot, so that * there is non-reboot way to recover if something goes wrong. */static intether3_open(struct device *dev){	MOD_INC_USE_COUNT;	if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev)) {	    	MOD_DEC_USE_COUNT;		return -EAGAIN;	}	dev->tbusy = 0;	dev->interrupt = 0;	dev->start = 1;	ether3_init_for_open(dev);	return 0;}/* * The inverse routine to ether3_open(). */static intether3_close(struct device *dev){	struct dev_priv *priv = (struct dev_priv *)dev->priv;	dev->tbusy = 1;	dev->start = 0;	disable_irq(dev->irq);	ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND);	priv->regs.command = 0;	while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON));	ether3_outb(0x80, REG_CONFIG2 + 1);	ether3_outw(0, REG_COMMAND);	free_irq(dev->irq, dev);	MOD_DEC_USE_COUNT;	return 0;}/* * Get the current statistics.	This may be called with the card open or * closed. */static struct enet_statistics *ether3_getstats(struct device *dev){	struct dev_priv *priv = (struct dev_priv *)dev->priv;	return &priv->stats;}/* * Set or clear promiscuous/multicast mode filter for this adaptor. * * We don't attempt any packet filtering.  The card may have a SEEQ 8004 * in which does not have the other ethernet address registers present... */static void ether3_setmulticastlist(struct device *dev){	struct dev_priv *priv = (struct dev_priv *)dev->priv;	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);}/* * Transmit a packet */static intether3_sendpacket(struct sk_buff *skb, struct device *dev){	struct dev_priv *priv = (struct dev_priv *)dev->priv;retry:	if (!dev->tbusy) {		if (skb) {		    /* Block a timer-based transmit from overlapping. */		    if (!set_bit(0, (void *)&dev->tbusy)) {		    	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, FREE_WRITE);				priv->stats.tx_dropped ++;				dev->tbusy = 0;				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;			if (priv->tx_tail != next_ptr)				dev->tbusy = 0;			restore_flags(flags);			dev_kfree_skb(skb, FREE_WRITE);			return 0;		    } else {			printk("%s: transmitter access conflict.\n", dev->name);			return 1;		    }		} else {		    /* If some higher layer thinks we've missed an tx-done interrupt		     * we are passed NULL. Caution: dev_tint() handles the cli()/sti()		     * itself.		     */		    dev_tint(dev);		    return 0;		}	} else {		/* If we get here, some higher level has decided we are broken.		 * There should really be a "kick me" function call instead.		 */		int tickssofar = jiffies - dev->trans_start;		unsigned long flags;		if (tickssofar < 5)			return 1;		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);		dev->tbusy = 0;		priv->regs.config2 |= CFG2_CTRLO;		priv->stats.tx_errors += 1;		ether3_outw(priv->regs.config2, REG_CONFIG2);		dev->trans_start = jiffies;		priv->tx_head = priv->tx_tail = 0;		goto retry;	}}static voidether3_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct device *dev = (struct 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;	dev->interrupt = 1;	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);	}	dev->interrupt = 0;#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 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 enet_statistics *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 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);//printk("%s: processing tx packet @ %04X (status=%08lX)\n", dev->name, tx_tail, status);		/*		 * 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;		dev->tbusy = 0;		mark_bh(NET_BH);	/* Inform upper layers. */	}}#ifdef MODULEchar ethernames[MAX_ECARDS][9];static struct device *my_ethers[MAX_ECARDS];static struct expansion_card *ec[MAX_ECARDS];intinit_module(void){	int i;	for(i = 0; i < MAX_ECARDS; i++) {		my_ethers[i] = NULL;		ec[i] = NULL;		strcpy(ethernames[i], "        ");	}	i = 0;	ecard_startfind();	do {		if ((ec[i] = ecard_find(0, ether3_cids)) == NULL)			break;		my_ethers[i] = (struct device *)kmalloc(sizeof(struct device), GFP_KERNEL);		memset(my_ethers[i], 0, sizeof(struct device));		my_ethers[i]->init = ether3_probe1;		my_ethers[i]->name = ethernames[i];		ether3_get_dev(my_ethers[i], ec[i]);		if(register_netdev(my_ethers[i]) != 0) {			for (i = 0; i < MAX_ECARDS; i++) {				if(my_ethers[i]) {					kfree(my_ethers[i]);					my_ethers[i] = NULL;				}				if(ec[i]) {					ecard_release(ec[i]);					ec[i] = NULL;				}			}			return -EIO;		}		i++;	}	while(i < MAX_ECARDS);	return i != 0 ? 0 : -ENODEV;}voidcleanup_module(void){	int i;	for (i = 0; i < MAX_ECARDS; i++) {		if (my_ethers[i]) {		  	release_region(my_ethers[i]->base_addr, 128);			unregister_netdev(my_ethers[i]);			my_ethers[i] = NULL;		}		if (ec[i]) {			ecard_release(ec[i]);			ec[i] = NULL;		}	}}#endif /* MODULE */

⌨️ 快捷键说明

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