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

📄 em86xx_eth.c

📁 bootloader源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (em86xx_set_mac(dev))		return(-EIO);	/* stop MAC engine */	em86xx_write_reg(EM86XX_CR_REG, 0x0); #ifndef USE_HW_FILTERING	/* set up multicast hash table to MCHTHR MCHTLR */	/* set multicast hash table to accept all */	em86xx_write_reg(EM86XX_MCHTHR_REG, 0xffffffff); 	em86xx_write_reg(EM86XX_MCHTLR_REG, 0xffffffff); #else	/* clear hash table */        em86xx_write_reg( EM86XX_MCHTHR_REG, 0 );        em86xx_write_reg( EM86XX_MCHTLR_REG, 0 );        /* set the broadcast address */        n = em86xx_hash(broadcast_addr);        if( n >= 32 )        	em86xx_write_reg(EM86XX_MCHTHR_REG, 1 << (n-32) );        else                em86xx_write_reg(EM86XX_MCHTLR_REG, 1 << n );#endif	/* resetting descriptors */#ifdef BOOTLOADER        if (em86xx_eth_reset_desc(dev, &reset_flag))#else        if (em86xx_eth_reset_desc(&em86xx_eth_dev, &reset_flag))#endif		return(-EIO);	/* configure IFR with PHY and speed, as well as PHY */	em86xx_link_config(dev, max_link_loop);	return 0;}#ifndef BOOTLOADER/* Monitor the status of link, re-do link initialization if necessary. */static void em86xx_eth_link_monitor(unsigned long dummy){	unsigned long link_status;	struct net_device *dev = (struct net_device *)dummy;	int res;	/* Setup the link/configuration is not done so. */	if ((link_up == 0) || (link_configured == 0)) {		res = em86xx_eth_hw_init(dev);	}	/* Get link status and adjust the delay loop accordingly */	link_status = (em86xx_mii_read(1, GEN_sts) & LINK) ;	if (link_status) {  		if ((link_configured != 0) && (link_up != 0)) {    			if (!netif_carrier_ok(dev)) {	      			netif_carrier_on(dev); /* Up and running, turn netif on */	      	        	max_link_loop = DEF_LINK_LOOP;	      	        	ld_count >>= 2;        	      		if (ld_count == 0)      					ld_count = 1;	    		}	        } else {	      		ld_count <<= 1;	      		max_link_loop = ld_count * DEF_LINK_LOOP;		      		if (max_link_loop > DEF_MAX_LINK_LOOP)	      			max_link_loop = DEF_MAX_LINK_LOOP;		              	netif_carrier_off(dev);	              	link_configured = 0;	     	}	} else {		MSG_PRINT("%s: detected link down.\n", dev->name);	        ld_count <<= 1;	        max_link_loop = ld_count * DEF_LINK_LOOP;	  	if (max_link_loop > DEF_MAX_LINK_LOOP)    			max_link_loop = DEF_MAX_LINK_LOOP;	  	netif_carrier_off(dev);	  	link_up = link_configured = 0;	}	/* Schedule for the next time */	mod_timer(&eth_timer, jiffies + HZ*5); }#endif/* Setting rx/tx descriptors */static void em86xx_eth_setup_desc(void){	register int i;	struct em86xx_desc *desc_ptr = NULL;	unsigned long base_addr = 0;	/* Setup rx descriptor */	desc_ptr = (struct em86xx_desc *)(rxdsc);	for (i = 0; i < (num_rxdesc - 1); i++, desc_ptr++) {		desc_ptr->desc3 = (unsigned long)(desc_ptr + 1);		desc_ptr->desc1 = (DescChain | R_BUF_SIZE);  		desc_ptr->desc0 = DescOwnByDma; 	}	desc_ptr->desc3 = (unsigned long)(rxdsc);	desc_ptr->desc1 = (DescChain | DescEndOfRing | R_BUF_SIZE);	desc_ptr->desc0 = DescOwnByDma; 	/* Setup tx descriptor */	desc_ptr = (struct em86xx_desc *)(txdsc); 	for (i =0;  i < (num_txdesc - 1); i++, desc_ptr++) {		desc_ptr->desc3 = (unsigned long)(desc_ptr + 1);		desc_ptr->desc1 = (TX_DESC1_FLAGS | T_BUF_SIZE);  		desc_ptr->desc0 = DescOwnByCPU;	}	desc_ptr->desc3 = (unsigned long)(txdsc);	desc_ptr->desc1 = (TX_DESC1_FLAGS | DescEndOfRing | T_BUF_SIZE);	desc_ptr->desc0 = DescOwnByCPU;	/* Point rx descriptor to buffer */	desc_ptr = (struct em86xx_desc *)(rxdsc);       	base_addr = (unsigned long)(rxbuf); 	for (i = 0; i < num_rxdesc; i++, desc_ptr++, base_addr += R_BUF_SIZE) 		desc_ptr->desc2 = base_addr;	/* Point tx descriptor to buffer */	desc_ptr = (struct em86xx_desc *)(txdsc);        base_addr = (unsigned long)(txbuf);	for (i = 0; i < num_txdesc; i++, desc_ptr++, base_addr += T_BUF_SIZE) 		desc_ptr->desc2 = base_addr;}/* Starting up the ethernet device */static int em86xx_eth_open(struct net_device *dev){	EM86XX_ETH_PRIV *private = (EM86XX_ETH_PRIV *)dev->priv;	if ((dev == NULL) || (private == NULL))		return(-EIO);	DBG_PRINT("%s: starting interface.\n", dev->name);#ifdef BOOTLOADER	em86xx_eth_hw_init(dev);        dev->state = NETDEV_UP;#else	/* Schedule timer for monitoring link status */	init_timer(&eth_timer);	eth_timer.function = em86xx_eth_link_monitor;	eth_timer.data = (unsigned long)dev;	mod_timer(&eth_timer, jiffies + HZ);	netif_start_queue(dev);#endif /*BOOTLOADER*/	return 0;}/* Stopping the ethernet device */static int em86xx_eth_close(struct net_device *dev){	if (dev == NULL)  		return(-EIO);	/* Turn off IRQ and stop receive/transmit */	em86xx_write_reg(EM86XX_CR_REG, 0);	em86xx_write_reg(EM86XX_IER_REG, 0);#ifdef BOOTLOADER	dev->state = NETDEV_DOWN;#else	/* Kill timer */	del_timer_sync(&eth_timer);	/* Stop the transmit queue */	netif_stop_queue(dev);	link_up = link_configured = 0;#endif /*BOOTLOADER*/	return 0;}#ifndef BOOTLOADER/* Setup multicast list */static void em86xx_eth_set_multicast_list(struct net_device *dev){	/* Multicast hash filter */        u32 mc_filter[2];        int i, rx_mode;	rx_mode =  em86xx_read_reg(EM86XX_MACCR_REG);          DBG_PRINT(KERN_DEBUG"%s:   set_rx_mode(0x%x) done -- rx_mode=0x%x.\n",                           dev->name, dev->flags, rx_mode);        if (dev->flags & IFF_PROMISC) {                printk("%s: Promiscuous mode enabled.\n", dev->name);                rx_mode |= MacPromiscuousModeOn;                mc_filter[1] = mc_filter[0] = 0xffffffff;        } else {                struct dev_mc_list *mclist;                rx_mode &=  ~MacPromiscuousModeOn;                mc_filter[1] = mc_filter[0] = 0;                for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;                         i++, mclist = mclist->next){			int n = 0;			n = em86xx_hash(mclist->dmi_addr);			if( n >= 32 )	        	        mc_filter[1] |= 1 << (n-32) ;        		else	        	        mc_filter[0] |= 1 << n ;		}        }	em86xx_write_reg(EM86XX_MACCR_REG, rx_mode );        em86xx_write_reg(EM86XX_MCHTLR_REG, mc_filter[0]);        em86xx_write_reg(EM86XX_MCHTHR_REG, mc_filter[1]);        return;}#endif/* Transmit a packet */#ifdef BOOTLOADERstatic int em86xx_eth_tx(struct sk_buff *skb, struct net_device *dev, int async)#elsestatic int em86xx_eth_tx(struct sk_buff *skb, struct net_device *dev)#endif{	EM86XX_ETH_PRIV *private = NULL;	volatile struct em86xx_desc *desc_ptr = NULL;	struct net_device_stats *stats = NULL;	unsigned long length 	= 0;	//int j;	if ((skb == NULL) || (dev == NULL)) {		DBG_PRINT("em86xx_eth_tx: null dev\n");		return(-EIO);	} else if ((link_up == 0) || (link_configured == 0)) {		DBG_PRINT("em86xx_eth_tx: link is not up yet\n");#ifndef BOOTLOADER		netif_carrier_off(dev);#endif		return(-EIO); 	} else if ((length = ((ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN)) > T_BUF_SIZE) {      		DBG_PRINT("em86xx_eth_tx: too big\n");		return(-ENOMEM); 	}	private = (EM86XX_ETH_PRIV *)dev->priv;	stats = &(private->stats);	/* Send packet to device */	desc_ptr = (volatile struct em86xx_desc *)(&txdsc[private->next_txidx]);	if (desc_ptr->desc0 & DescOwnByDma) {		stats->tx_dropped++;        	ERR_PRINT("%s desc_ptr=0x%x: tx error (descriptor not owned by CPU).\n",				 dev->name, (u32)desc_ptr);		return(-EIO);	} 	/* Check if previous transmission has error */	if (desc_ptr->desc0 & TX_ERROR_FLAGS) {		ERR_PRINT("%s: tx error 0x%08lx\n", dev->name, desc_ptr->desc0);		/* Update stats */		stats->tx_errors++;		stats->tx_packets--;		stats->tx_bytes -= (desc_ptr->desc1 & DescSize1Mask);	}	/* Copy packet data to tx buffer */	DBG_PRINT("tx copy data from skb->data=0x%x to desc2=0x%x length=0x%lx\n",		(u32)skb->data, desc_ptr->desc2, length );	memcpy((unsigned char *)(desc_ptr->desc2), skb->data, length);	/* Setup tx descriptor */	desc_ptr->desc1 = ( TX_DESC1_FLAGS | length );	if (private->next_txidx == (num_txdesc - 1))		desc_ptr->desc1 |=  DescEndOfRing ;	desc_ptr->desc0 |= DescOwnByDma;#ifdef BOOTLOADER        private->next_txidx = imodulus((private->next_txidx + 1), num_txdesc);#else	dev->trans_start = jiffies;	private->next_txidx = ((private->next_txidx + 1) % num_txdesc);#endif	/* Start transmission (should be in suspend mode already) */	em86xx_write_reg(EM86XX_TPDR_REG, 0x0);	/* Update stats */	stats->tx_packets++;	stats->tx_bytes += length;	/* Free up socket buffer */#ifdef BOOTLOADER	async = 0;	skb_free(skb);#else	dev_kfree_skb(skb);#endif	return 0;}static inline int is_sw_filtered_packet(struct net_device *dev, unsigned char *data){#ifdef USE_SW_FILTERING        if (((data[0] & 0x80) == 0) && (dev->dev_addr[5] != data[5]))                return 1;        else                return 0;#else        return 0;#endif}/* Receiving packet(s) */static int em86xx_eth_rx(struct net_device *dev){	EM86XX_ETH_PRIV *private 	= NULL;	struct sk_buff *skb 		= NULL;	struct net_device_stats *stats 	= NULL;	unsigned char *data 		= NULL;	volatile struct em86xx_desc *desc_ptr = NULL;	unsigned long length 	= 0;	unsigned long dsc	= 0;	unsigned long count 	= 0, cnt = 0;	if (dev == NULL)  		return(-EIO);	else {  		private = (EM86XX_ETH_PRIV *)dev->priv;	  	stats = &(private->stats);	}	/* Go thru descriptors list until we ran out or encounterred the one	   being processed by DMA */#ifdef BOOTLOADER 	for (cnt = 0, count = private->last_rxidx; cnt < num_rxdesc; cnt++, count = imodulus(count + 1, num_rxdesc)) {#else	for (cnt = 0, count = private->last_rxidx; cnt < num_rxdesc; cnt++, count = ((count + 1) % num_rxdesc)) {#endif		desc_ptr = (volatile struct em86xx_desc *)(&rxdsc[count]);	 	dsc = desc_ptr->desc0;	  	if (dsc & DescOwnByDma) {    			/* DMA is processing this one, break out the loop */			break;    		} 		/*filter out those are not for me */      		data = (unsigned char *)(desc_ptr->desc2);		if (is_sw_filtered_packet(dev, data)) {			ERR_PRINT("%s: mac mismatched, dropped.\n", dev->name);		} else	if ( dsc & RX_ERROR_FLAGS ) {      			ERR_PRINT("%s: rx error 0x%08lx:%ld desc1=0x%08x\n", 				dev->name, dsc, count, (u32)desc_ptr->desc1);			/* We dropped any error packet */		        stats->rx_errors++;		 } else if ((dsc & MP_FRAME_FLAGS) != MP_FRAME_FLAGS) {	        	 ERR_PRINT("%s: multi-packet frame detected 0x%08lx\n", dev->name, dsc);		        /* We don't handle multi-packet frame, for now */		        stats->rx_dropped++;		 } else if ((length = ((dsc & DescFrameLengthMask) >> DescFrameLengthShift)) > R_BUF_SIZE) {      			ERR_PRINT("%s: rx dropped (size too large: %ld)\n", dev->name, length);			stats->rx_dropped++;#ifdef BOOTLOADER                 } else if ((skb = skb_alloc(length)) == NULL) {#else		 } else if ((skb = dev_alloc_skb(length + 2)) == NULL) {#endif			 ERR_PRINT("%s: rx dropped (memory unavailable)\n", dev->name);	        	 stats->rx_dropped++;		 } else {		  	 skb->dev = dev;#ifdef BOOTLOADER                         skb->len = length - 4;                         memcpy(skb->data, data, length-4);                         skb_put(skb);                         /* Update stats */                         stats->rx_packets++;                         stats->rx_bytes += length;#else		         skb_reserve(skb, 2);		         memcpy(skb_put(skb, length), data, length-4); 		         skb->protocol = eth_type_trans(skb, dev);     			 skb->ip_summed = CHECKSUM_NONE;		         /* Send the packet to kernel */		         netif_rx(skb);  	        	 /* Update stats */		       	 stats->rx_packets++;		         stats->rx_bytes += length;		       	 dev->last_rx = jiffies;

⌨️ 快捷键说明

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