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

📄 ethernet.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			*R_DMA_CH1_CLR_INTR =				IO_STATE(R_DMA_CH1_CLR_INTR, clr_eop, do) |				IO_STATE(R_DMA_CH1_CLR_INTR, clr_descr, do);						/* now, we might have gotten another packet			   so we have to loop back and check if so */		}	}}/* the transmit dma channel interrupt * * this is supposed to free the skbuff which was pending during transmission, * and inform the kernel that we can send one more buffer */static voide100tx_interrupt(int irq, void *dev_id, struct pt_regs * regs){	struct net_device *dev = (struct net_device *)dev_id;	unsigned long irqbits = *R_IRQ_MASK2_RD;	struct net_local *np = (struct net_local *)dev->priv;	/* check for a dma0_eop interrupt */	if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) { 		/* This protects us from concurrent execution of		 * our dev->hard_start_xmit function above.		 */		spin_lock(&np->lock);				/* acknowledge the eop interrupt */		*R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);		if (*R_DMA_CH0_FIRST == 0 && tx_skb) {			np->stats.tx_bytes += tx_skb->len;			np->stats.tx_packets++;			/* dma is ready with the transmission of the data in tx_skb, so now			   we can release the skb memory */			dev_kfree_skb_irq(tx_skb);			tx_skb = 0;			netif_wake_queue(dev);		} else {			printk(KERN_WARNING "%s: tx weird interrupt\n",			       cardname);		}		spin_unlock(&np->lock);	}}static voide100nw_interrupt(int irq, void *dev_id, struct pt_regs * regs){	struct net_device *dev = (struct net_device *)dev_id;	struct net_local *np = (struct net_local *)dev->priv;	unsigned long irqbits = *R_IRQ_MASK0_RD;	/* check for underrun irq */	if (irqbits & IO_STATE(R_IRQ_MASK0_RD, underrun, active)) { 		*R_NETWORK_TR_CTRL = IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr);		np->stats.tx_errors++;		D(printk("ethernet receiver underrun!\n"));	}	/* check for overrun irq */	if (irqbits & IO_STATE(R_IRQ_MASK0_RD, overrun, active)) { 		update_rx_stats(&np->stats); /* this will ack the irq */		D(printk("ethernet receiver overrun!\n"));	}	/* check for excessive collision irq */	if (irqbits & IO_STATE(R_IRQ_MASK0_RD, excessive_col, active)) { 		*R_NETWORK_TR_CTRL = IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr);		np->stats.tx_errors++;		D(printk("ethernet excessive collisions!\n"));	}}/* We have a good packet(s), get it/them out of the buffers. */static voide100_rx(struct net_device *dev){	struct sk_buff *skb;	int length = 0;	struct net_local *np = (struct net_local *)dev->priv;	struct etrax_dma_descr *mySaveRxDesc = myNextRxDesc;	unsigned char *skb_data_ptr;#ifdef ETHDEBUG	int i;#endif	if (!led_active && jiffies > led_next_time) {		/* light the network leds depending on the current speed. */		e100_set_network_leds(NETWORK_ACTIVITY);		/* Set the earliest time we may clear the LED */		led_next_time = jiffies + NET_FLASH_TIME;		led_active = 1;		mod_timer(&clear_led_timer, jiffies + HZ/10);	}	/* If the packet is broken down in many small packages then merge	 * count how much space we will need to alloc with skb_alloc() for	 * it to fit.	 */	while (!(myNextRxDesc->status & d_eop)) {		length += myNextRxDesc->sw_len; /* use sw_len for the first descs */		myNextRxDesc->status = 0;		myNextRxDesc = phys_to_virt(myNextRxDesc->next);	}	length += myNextRxDesc->hw_len; /* use hw_len for the last descr */	((struct net_local *)dev->priv)->stats.rx_bytes += length;#ifdef ETHDEBUG	printk("Got a packet of length %d:\n", length);	/* dump the first bytes in the packet */	skb_data_ptr = (unsigned char *)phys_to_virt(mySaveRxDesc->buf);	for (i = 0; i < 8; i++) {		printk("%d: %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", i * 8,		       skb_data_ptr[0],skb_data_ptr[1],skb_data_ptr[2],skb_data_ptr[3],		       skb_data_ptr[4],skb_data_ptr[5],skb_data_ptr[6],skb_data_ptr[7]);		skb_data_ptr += 8;	}#endif	skb = dev_alloc_skb(length - ETHER_HEAD_LEN);	if (!skb) {		np->stats.rx_errors++;		printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",		       dev->name);		return;	}	skb_put(skb, length - ETHER_HEAD_LEN);        /* allocate room for the packet body */	skb_data_ptr = skb_push(skb, ETHER_HEAD_LEN); /* allocate room for the header */#ifdef ETHDEBUG	printk("head = 0x%x, data = 0x%x, tail = 0x%x, end = 0x%x\n",	       skb->head, skb->data, skb->tail, skb->end);	printk("copying packet to 0x%x.\n", skb_data_ptr);#endif	/* this loop can be made using max two memcpy's if optimized */	while (mySaveRxDesc != myNextRxDesc) {		memcpy(skb_data_ptr, phys_to_virt(mySaveRxDesc->buf),		       mySaveRxDesc->sw_len);		skb_data_ptr += mySaveRxDesc->sw_len;		mySaveRxDesc = phys_to_virt(mySaveRxDesc->next);	}	memcpy(skb_data_ptr, phys_to_virt(mySaveRxDesc->buf),	       mySaveRxDesc->hw_len);	skb->dev = dev;	skb->protocol = eth_type_trans(skb, dev);	/* Send the packet to the upper layers */	netif_rx(skb);	/* Prepare for next packet */	myNextRxDesc->status = 0;	myPrevRxDesc = myNextRxDesc;	myNextRxDesc = phys_to_virt(myNextRxDesc->next);	myPrevRxDesc->ctrl |= d_eol;	myLastRxDesc->ctrl &= ~d_eol;	myLastRxDesc = myPrevRxDesc;	return;}/* The inverse routine to net_open(). */static inte100_close(struct net_device *dev){	struct net_local *np = (struct net_local *)dev->priv;	printk("Closing %s.\n", dev->name);	netif_stop_queue(dev);	*R_NETWORK_GEN_CONFIG =		IO_STATE(R_NETWORK_GEN_CONFIG, phy,    mii_clk) |		IO_STATE(R_NETWORK_GEN_CONFIG, enable, off);		*R_IRQ_MASK0_CLR =		IO_STATE(R_IRQ_MASK0_CLR, overrun, clr) |		IO_STATE(R_IRQ_MASK0_CLR, underrun, clr) |		IO_STATE(R_IRQ_MASK0_CLR, excessive_col, clr);		*R_IRQ_MASK2_CLR =		IO_STATE(R_IRQ_MASK2_CLR, dma0_descr, clr) |		IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr) |		IO_STATE(R_IRQ_MASK2_CLR, dma1_descr, clr) |		IO_STATE(R_IRQ_MASK2_CLR, dma1_eop, clr);	/* Stop the receiver and the transmitter */	RESET_DMA(NETWORK_TX_DMA_NBR);	RESET_DMA(NETWORK_RX_DMA_NBR);	/* Flush the Tx and disable Rx here. */	free_irq(NETWORK_DMA_RX_IRQ_NBR, (void *)dev);	free_irq(NETWORK_DMA_TX_IRQ_NBR, (void *)dev);	free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev);	free_dma(NETWORK_TX_DMA_NBR);	free_dma(NETWORK_RX_DMA_NBR);	/* Update the statistics here. */	update_rx_stats(&np->stats);	update_tx_stats(&np->stats);	return 0;}static inte100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	/* Maybe default should return -EINVAL instead? */	switch (cmd) {		case SET_ETH_SPEED_10:                  /* 10 Mbps */			e100_set_speed(10);			break;		case SET_ETH_SPEED_100:                /* 100 Mbps */			e100_set_speed(100);			break;		case SET_ETH_SPEED_AUTO:              /* Auto negotiate speed */			e100_set_speed(0);			break;		case SET_ETH_DUPLEX_HALF:              /* Hhalf duplex. */			e100_set_duplex(half);			break;		case SET_ETH_DUPLEX_FULL:              /* Full duplex. */			e100_set_duplex(full);			break;		case SET_ETH_DUPLEX_AUTO:             /* Autonegotiate duplex*/			e100_set_duplex(autoneg);			break;		default: /* Auto neg */			e100_set_speed(0);			e100_set_duplex(autoneg);			break;	}	return 0;}static voidupdate_rx_stats(struct net_device_stats *es){	unsigned long r = *R_REC_COUNTERS;	/* update stats relevant to reception errors */	es->rx_fifo_errors += IO_EXTRACT(R_REC_COUNTERS, congestion, r);	es->rx_crc_errors += IO_EXTRACT(R_REC_COUNTERS, crc_error, r);	es->rx_frame_errors += IO_EXTRACT(R_REC_COUNTERS, alignment_error, r);	es->rx_length_errors += IO_EXTRACT(R_REC_COUNTERS, oversize, r);}static voidupdate_tx_stats(struct net_device_stats *es){	unsigned long r = *R_TR_COUNTERS;	/* update stats relevant to transmission errors */	es->collisions +=		IO_EXTRACT(R_TR_COUNTERS, single_col, r) +		IO_EXTRACT(R_TR_COUNTERS, multiple_col, r);	es->tx_errors += IO_EXTRACT(R_TR_COUNTERS, deferred, r);}/* * Get the current statistics. * This may be called with the card open or closed. */static struct net_device_stats *e100_get_stats(struct net_device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	update_rx_stats(&lp->stats);	update_tx_stats(&lp->stats);	return &lp->stats;}/* * Set or clear the multicast filter for this adaptor. * num_addrs == -1	Promiscuous mode, receive all packets * num_addrs == 0	Normal mode, clear multicast list * num_addrs > 0	Multicast mode, receive normal and MC packets, *			and do best-effort filtering. */static voidset_multicast_list(struct net_device *dev){	int num_addr = dev->mc_count;	unsigned long int lo_bits;	unsigned long int hi_bits;	if (dev->flags & IFF_PROMISC)	{		/* promiscuous mode */		lo_bits = 0xfffffffful;		hi_bits = 0xfffffffful;		/* Enable individual receive */		SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, individual, receive);		*R_NETWORK_REC_CONFIG = network_rec_config_shadow;	} else if (dev->flags & IFF_ALLMULTI) {		/* enable all multicasts */		lo_bits = 0xfffffffful;		hi_bits = 0xfffffffful;		/* Disable individual receive */		SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, individual, discard);		*R_NETWORK_REC_CONFIG =  network_rec_config_shadow;	} else if (num_addr == 0) {		/* Normal, clear the mc list */		lo_bits = 0x00000000ul;		hi_bits = 0x00000000ul;		/* Disable individual receive */		SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, individual, discard);		*R_NETWORK_REC_CONFIG =  network_rec_config_shadow;	} else {		/* MC mode, receive normal and MC packets */		char hash_ix;		struct dev_mc_list *dmi = dev->mc_list;		int i;		char *baddr;		lo_bits = 0x00000000ul;		hi_bits = 0x00000000ul;		for (i=0; i<num_addr; i++) {			/* Calculate the hash index for the GA registers */						hash_ix = 0;			baddr = dmi->dmi_addr;			hash_ix ^= (*baddr) & 0x3f;			hash_ix ^= ((*baddr) >> 6) & 0x03;			++baddr;			hash_ix ^= ((*baddr) << 2) & 0x03c;			hash_ix ^= ((*baddr) >> 4) & 0xf;			++baddr;			hash_ix ^= ((*baddr) << 4) & 0x30;			hash_ix ^= ((*baddr) >> 2) & 0x3f;			++baddr;			hash_ix ^= (*baddr) & 0x3f;			hash_ix ^= ((*baddr) >> 6) & 0x03;			++baddr;			hash_ix ^= ((*baddr) << 2) & 0x03c;			hash_ix ^= ((*baddr) >> 4) & 0xf;			++baddr;			hash_ix ^= ((*baddr) << 4) & 0x30;			hash_ix ^= ((*baddr) >> 2) & 0x3f;						hash_ix &= 0x3f;						if (hash_ix > 32) {				hi_bits |= (1 << (hash_ix-32));			}			else {				lo_bits |= (1 << hash_ix);			}			dmi = dmi->next;		}		/* Disable individual receive */		SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, individual, discard);		*R_NETWORK_REC_CONFIG = network_rec_config_shadow;	}	*R_NETWORK_GA_0 = lo_bits;	*R_NETWORK_GA_1 = hi_bits;}voide100_hardware_send_packet(char *buf, int length){	D(printk("e100 send pack, buf 0x%x len %d\n", buf, length));	if (!led_active && jiffies > led_next_time) {		/* light the network leds depending on the current speed. */		e100_set_network_leds(NETWORK_ACTIVITY);		/* Set the earliest time we may clear the LED */		led_next_time = jiffies + NET_FLASH_TIME;		led_active = 1;		mod_timer(&clear_led_timer, jiffies + HZ/10);	}	/* configure the tx dma descriptor */	TxDesc.sw_len = length;	TxDesc.ctrl = d_eop | d_eol | d_wait;	TxDesc.buf = virt_to_phys(buf);	/* setup the dma channel and start it */	*R_DMA_CH0_FIRST = virt_to_phys(&TxDesc);	*R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, start);}static voide100_clear_network_leds(unsigned long dummy){	if (led_active && jiffies > led_next_time) {		e100_set_network_leds(NO_NETWORK_ACTIVITY);		/* Set the earliest time we may set the LED */		led_next_time = jiffies + NET_FLASH_PAUSE;		led_active = 0;	}}static voide100_set_network_leds(int active){#if defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK)	int light_leds = (active == NO_NETWORK_ACTIVITY);#elif defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY)	int light_leds = (active == NETWORK_ACTIVITY);#else#error "Define either CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK or CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY"#endif	if (!current_speed) {		/* Make LED red, link is down */		LED_NETWORK_SET(LED_RED);	}	else if (light_leds) {		if (current_speed == 10) {			LED_NETWORK_SET(LED_ORANGE);		} else {			LED_NETWORK_SET(LED_GREEN);		}	}	else {		LED_NETWORK_SET(LED_OFF);	}}static struct net_device dev_etrax_ethernet;  /* only got one */static intetrax_init_module(void){	struct net_device *d = &dev_etrax_ethernet;	d->init = etrax_ethernet_init;	if (register_netdev(d) == 0)		return 0;	else		return -ENODEV;}module_init(etrax_init_module);

⌨️ 快捷键说明

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