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

📄 au1000_eth.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
		netif_stop_queue(dev);	}	/* disable the interrupt */	free_irq(dev->irq, dev);	spin_unlock_irqrestore(&aup->lock, flags);	reset_mac(dev);	MOD_DEC_USE_COUNT;	return 0;}static inline void update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len){	struct au1000_private *aup = (struct au1000_private *) dev->priv;	struct net_device_stats *ps = &aup->stats;	ps->tx_packets++;	ps->tx_bytes += pkt_len;	if (status & TX_FRAME_ABORTED) {		ps->tx_errors++;		ps->tx_aborted_errors++;		if (status & (TX_NO_CARRIER | TX_LOSS_CARRIER))			ps->tx_carrier_errors++;	}}/* * Called from the interrupt service routine to acknowledge * the TX DONE bits.  This is a must if the irq is setup as * edge triggered. */static void au1000_tx_ack(struct net_device *dev){	struct au1000_private *aup = (struct au1000_private *) dev->priv;	volatile tx_dma_t *ptxd;	ptxd = aup->tx_dma_ring[aup->tx_tail];	while (ptxd->buff_stat & TX_T_DONE) {		update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);		ptxd->buff_stat &= ~TX_T_DONE;		ptxd->len = 0;		sync();		aup->tx_tail = (aup->tx_tail + 1) & (NUM_TX_DMA - 1);		ptxd = aup->tx_dma_ring[aup->tx_tail];		if (aup->tx_full) {			aup->tx_full = 0;			netif_wake_queue(dev);		}	}}/* * Au1000 transmit routine. */static int au1000_tx(struct sk_buff *skb, struct net_device *dev){	struct au1000_private *aup = (struct au1000_private *) dev->priv;	//unsigned long flags;	volatile tx_dma_t *ptxd;	u32 buff_stat;	db_dest_t *pDB;	int i;	if (au1000_debug > 4)		printk("%s: tx: aup %x len=%d, data=%p, head %d\n",		       dev->name, (unsigned)aup, skb->len, skb->data, aup->tx_head);	/* Prevent interrupts from changing the Tx ring */	//spin_lock_irqsave(&aup->lock, flags);		ptxd = aup->tx_dma_ring[aup->tx_head];	buff_stat = ptxd->buff_stat;	if (buff_stat & TX_DMA_ENABLE) {		/* We've wrapped around and the transmitter is still busy */		netif_stop_queue(dev);		aup->tx_full = 1;		//spin_unlock_irqrestore(&aup->lock, flags);		return 1;	}	else if (buff_stat & TX_T_DONE) {		update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);		ptxd->len = 0;	}	if (aup->tx_full) {		aup->tx_full = 0;		netif_wake_queue(dev);	}	pDB = aup->tx_db_inuse[aup->tx_head];	memcpy((void *)pDB->vaddr, skb->data, skb->len);	if (skb->len < MAC_MIN_PKT_SIZE) {		for (i=skb->len; i<MAC_MIN_PKT_SIZE; i++) { 			((char *)pDB->vaddr)[i] = 0;		}		ptxd->len = MAC_MIN_PKT_SIZE;	}	else		ptxd->len = skb->len;	ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;	sync();	dev_kfree_skb(skb);	aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1);	dev->trans_start = jiffies;	//spin_unlock_irqrestore(&aup->lock, flags);	return 0;}static inline void update_rx_stats(struct net_device *dev, u32 status){	struct au1000_private *aup = (struct au1000_private *) dev->priv;	struct net_device_stats *ps = &aup->stats;	ps->rx_packets++;	if (status & RX_MCAST_FRAME)		ps->multicast++;	if (status & RX_ERROR) {		ps->rx_errors++;		if (status & RX_MISSED_FRAME)			ps->rx_missed_errors++;		if (status & (RX_OVERLEN | RX_OVERLEN | RX_LEN_ERROR))			ps->rx_length_errors++;		if (status & RX_CRC_ERROR)			ps->rx_crc_errors++;		if (status & RX_COLL)			ps->collisions++;	}	else 		ps->rx_bytes += status & RX_FRAME_LEN_MASK;}/* * Au1000 receive routine. */static int au1000_rx(struct net_device *dev){	struct au1000_private *aup = (struct au1000_private *) dev->priv;	struct sk_buff *skb;	volatile rx_dma_t *prxd;	u32 buff_stat, status;	db_dest_t *pDB;	if (au1000_debug > 4)		printk("%s: au1000_rx head %d\n", dev->name, aup->rx_head);	prxd = aup->rx_dma_ring[aup->rx_head];	buff_stat = prxd->buff_stat;	while (buff_stat & RX_T_DONE)  {		status = prxd->status;		pDB = aup->rx_db_inuse[aup->rx_head];		update_rx_stats(dev, status);		if (!(status & RX_ERROR))  {			/* good frame */			skb = dev_alloc_skb((status & RX_FRAME_LEN_MASK) + 2);			if (skb == NULL) {				printk(KERN_ERR				       "%s: Memory squeeze, dropping packet.\n",				       dev->name);				aup->stats.rx_dropped++;				continue;			}			skb->dev = dev;			skb_reserve(skb, 2);	/* 16 byte IP header align */			eth_copy_and_sum(skb, (unsigned char *)pDB->vaddr, 					status & RX_FRAME_LEN_MASK, 0);			skb_put(skb, status & RX_FRAME_LEN_MASK); /* Make room */			skb->protocol = eth_type_trans(skb, dev);			netif_rx(skb);	/* pass the packet to upper layers */		}		else {			if (au1000_debug > 4) {				if (status & RX_MISSED_FRAME) 					printk("rx miss\n");				if (status & RX_WDOG_TIMER) 					printk("rx wdog\n");				if (status & RX_RUNT) 					printk("rx runt\n");				if (status & RX_OVERLEN) 					printk("rx overlen\n");				if (status & RX_COLL)					printk("rx coll\n");				if (status & RX_MII_ERROR)					printk("rx mii error\n");				if (status & RX_CRC_ERROR)					printk("rx crc error\n");				if (status & RX_LEN_ERROR)					printk("rx len error\n");				if (status & RX_U_CNTRL_FRAME)					printk("rx u control frame\n");				if (status & RX_MISSED_FRAME)					printk("rx miss\n");			}		}		prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);		aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1);		sync();		/* next descriptor */		prxd = aup->rx_dma_ring[aup->rx_head];		buff_stat = prxd->buff_stat;		dev->last_rx = jiffies;	}	return 0;}/* * Au1000 interrupt service routine. */void au1000_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = (struct net_device *) dev_id;	if (dev == NULL) {		printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);		return;	}	au1000_rx(dev);	au1000_tx_ack(dev);}/* * The Tx ring has been full longer than the watchdog timeout * value. The transmitter must be hung? */static void au1000_tx_timeout(struct net_device *dev){	printk(KERN_ERR "%s: au1000_tx_timeout: dev=%p\n", dev->name, dev);	reset_mac(dev);	au1000_init(dev);}static unsigned const ethernet_polynomial = 0x04c11db7U;static inline u32 ether_crc(int length, unsigned char *data){    int crc = -1;    while(--length >= 0) {		unsigned char current_octet = *data++;		int bit;		for (bit = 0; bit < 8; bit++, current_octet >>= 1)			crc = (crc << 1) ^				((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);    }    return crc;}static void set_rx_mode(struct net_device *dev){	struct au1000_private *aup = (struct au1000_private *) dev->priv;	/* fixme */	if (au1000_debug > 4) 		printk("%s: set_multicast: flags=%x\n", dev->name, dev->flags);	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */		aup->mac->control |= MAC_PROMISCUOUS;		printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);	} else if ((dev->flags & IFF_ALLMULTI)  ||			   dev->mc_count > MULTICAST_FILTER_LIMIT) {		aup->mac->control |= MAC_PASS_ALL_MULTI;		aup->mac->control &= ~MAC_PROMISCUOUS;		printk(KERN_INFO "%s: Pass all multicast\n", dev->name);	} else {		int i;		struct dev_mc_list *mclist;		u32 mc_filter[2];	/* Multicast hash filter */		mc_filter[1] = mc_filter[0] = 0;		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;			 i++, mclist = mclist->next) {			set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter);		}		aup->mac->multi_hash_high = mc_filter[1];		aup->mac->multi_hash_low = mc_filter[0];		aup->mac->control |= MAC_HASH_MODE;	}}static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	//struct au1000_private *aup = (struct au1000_private *) dev->priv;	u16 *data = (u16 *)&rq->ifr_data;	/* fixme */	switch(cmd) { 		case SIOCGMIIPHY:		/* Get the address of the PHY in use. */		case SIOCDEVPRIVATE:		/* binary compat, remove in 2.5 */		data[0] = PHY_ADDRESS;		case SIOCGMIIREG:		/* Read the specified MII register. */		case SIOCDEVPRIVATE+1:		/* binary compat, remove in 2.5 */		//data[3] = mdio_read(ioaddr, data[0], data[1]); 		return 0;		case SIOCSMIIREG:		/* Write the specified MII register */		case SIOCDEVPRIVATE+2:		/* binary compat, remove in 2.5 */		if (!capable(CAP_NET_ADMIN))			return -EPERM;		//mdio_write(ioaddr, data[0], data[1], data[2]);		return 0;		default:		return -EOPNOTSUPP;	}}static int au1000_set_config(struct net_device *dev, struct ifmap *map){	struct au1000_private *aup = (struct au1000_private *) dev->priv;	u16 control;	if (au1000_debug > 4)  {		printk("%s: set_config called: dev->if_port %d map->port %x\n", 				dev->name, dev->if_port, map->port);	}	switch(map->port){		case IF_PORT_UNKNOWN: /* use auto here */   			printk("auto\\n");			dev->if_port = map->port;			/* Link Down: the timer will bring it up */			netif_carrier_off(dev);				/* read current control */			control = mdio_read(dev, aup->phy_addr, MII_CONTROL);			control &= ~(MII_CNTL_FDX | MII_CNTL_F100);			/* enable auto negotiation and reset the negotiation */			mdio_write(dev, aup->phy_addr,				   MII_CONTROL, control | MII_CNTL_AUTO | MII_CNTL_RST_AUTO);			break;    		case IF_PORT_10BASET: /* 10BaseT */         			printk("10baseT\n");			dev->if_port = map->port;				/* Link Down: the timer will bring it up */			netif_carrier_off(dev);			/* set Speed to 10Mbps, Half Duplex */			control = mdio_read(dev, aup->phy_addr, MII_CONTROL);			printk("read control %x\n", control);			control &= ~(MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_FDX);				/* disable auto negotiation and force 10M/HD mode*/			mdio_write(dev, aup->phy_addr, MII_CONTROL, control);			break;    		case IF_PORT_100BASET: /* 100BaseT */		case IF_PORT_100BASETX: /* 100BaseTx */ 			printk("100 base T/TX\n");			dev->if_port = map->port;				/* Link Down: the timer will bring it up */			netif_carrier_off(dev);				/* set Speed to 100Mbps, Half Duplex */			/* disable auto negotiation and enable 100MBit Mode */			control = mdio_read(dev, aup->phy_addr, MII_CONTROL);			printk("read control %x\n", control);			control &= ~(MII_CNTL_AUTO | MII_CNTL_FDX);			control |= MII_CNTL_F100;			mdio_write(dev, aup->phy_addr, MII_CONTROL, control);			break;    		case IF_PORT_100BASEFX: /* 100BaseFx */			printk("100 Base FX\n");			dev->if_port = map->port;				/* Link Down: the timer will bring it up */			netif_carrier_off(dev);				/* set Speed to 100Mbps, Full Duplex */			/* disable auto negotiation and enable 100MBit Mode */			control = mdio_read(dev, aup->phy_addr, MII_CONTROL);			control &= ~MII_CNTL_AUTO;			control |=  MII_CNTL_F100 | MII_CNTL_FDX;			mdio_write(dev, aup->phy_addr, MII_CONTROL, control);			break;		case IF_PORT_10BASE2: /* 10Base2 */		case IF_PORT_AUI: /* AUI */		/* These Modes are not supported (are they?)*/			printk(KERN_INFO "Not supported");			return -EOPNOTSUPP;			break;    		default:			printk("Invalid");			return -EINVAL;	}	return 0;}static struct net_device_stats *au1000_get_stats(struct net_device *dev){	struct au1000_private *aup = (struct au1000_private *) dev->priv;	if (au1000_debug > 4)		printk("%s: au1000_get_stats: dev=%p\n", dev->name, dev);	if (netif_device_present(dev)) {		return &aup->stats;	}	return 0;}

⌨️ 快捷键说明

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