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

📄 ethernet.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
 * If dev->base_addr == 0, probe all likely locations. * If dev->base_addr == 1, always return failure. * If dev->base_addr == 2, allocate space for the device and return success * (detachable devices only). */static int __initetrax_ethernet_init(void){	struct net_device *dev;	int i, err;	printk(KERN_INFO	       "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2003 Axis Communications AB\n");	dev = alloc_etherdev(sizeof(struct net_local));	if (!dev)		return -ENOMEM;	dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */		/* now setup our etrax specific stuff */	dev->irq = NETWORK_DMA_RX_IRQ_NBR; /* we really use DMATX as well... */	dev->dma = NETWORK_RX_DMA_NBR;	/* fill in our handlers so the network layer can talk to us in the future */	dev->open               = e100_open;	dev->hard_start_xmit    = e100_send_packet;	dev->stop               = e100_close;	dev->get_stats          = e100_get_stats;	dev->set_multicast_list = set_multicast_list;	dev->set_mac_address    = e100_set_mac_address;	dev->do_ioctl           = e100_ioctl;	dev->set_config		= e100_set_config;	dev->tx_timeout         = e100_tx_timeout;	/* Initialise the list of Etrax DMA-descriptors */	/* Initialise receive descriptors */	for (i = 0; i < NBR_OF_RX_DESC; i++) {		/* Allocate two extra cachelines to make sure that buffer used by DMA		 * does not share cacheline with any other data (to avoid cache bug)		 */		RxDescList[i].skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES);		RxDescList[i].descr.ctrl   = 0;		RxDescList[i].descr.sw_len = MAX_MEDIA_DATA_SIZE;		RxDescList[i].descr.next   = virt_to_phys(&RxDescList[i + 1]);		RxDescList[i].descr.buf    = L1_CACHE_ALIGN(virt_to_phys(RxDescList[i].skb->data));		RxDescList[i].descr.status = 0;		RxDescList[i].descr.hw_len = 0;             		prepare_rx_descriptor(&RxDescList[i].descr);	}	RxDescList[NBR_OF_RX_DESC - 1].descr.ctrl   = d_eol;	RxDescList[NBR_OF_RX_DESC - 1].descr.next   = virt_to_phys(&RxDescList[0]);	rx_queue_len = 0;	/* Initialize transmit descriptors */	for (i = 0; i < NBR_OF_TX_DESC; i++) {		TxDescList[i].descr.ctrl   = 0;		TxDescList[i].descr.sw_len = 0;		TxDescList[i].descr.next   = virt_to_phys(&TxDescList[i + 1].descr);		TxDescList[i].descr.buf    = 0;		TxDescList[i].descr.status = 0;		TxDescList[i].descr.hw_len = 0;		TxDescList[i].skb = 0;	}	TxDescList[NBR_OF_TX_DESC - 1].descr.ctrl   = d_eol;	TxDescList[NBR_OF_TX_DESC - 1].descr.next   = virt_to_phys(&TxDescList[0].descr);        	/* Initialise initial pointers */	myNextRxDesc  = &RxDescList[0];	myLastRxDesc  = &RxDescList[NBR_OF_RX_DESC - 1];	myPrevRxDesc  = &RxDescList[NBR_OF_RX_DESC - 1];	myFirstTxDesc = &TxDescList[0];	myNextTxDesc  = &TxDescList[0];	myLastTxDesc  = &TxDescList[NBR_OF_TX_DESC - 1];	/* Register device */	err = register_netdev(dev);	if (err) {		free_netdev(dev);		return err;	}	/* set the default MAC address */	e100_set_mac_address(dev, &default_mac);	/* Initialize speed indicator stuff. */	current_speed = 10;	current_speed_selection = 0; /* Auto */	speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;	speed_timer.function = e100_check_speed;        	clear_led_timer.function = e100_clear_network_leds;        	full_duplex = 0;	current_duplex = autoneg;	duplex_timer.expires = jiffies + NET_DUPLEX_CHECK_INTERVAL;			duplex_timer.function = e100_check_duplex;	/* Initialize group address registers to make sure that no */	/* unwanted addresses are matched */	*R_NETWORK_GA_0 = 0x00000000;	*R_NETWORK_GA_1 = 0x00000000;	return 0;}/* set MAC address of the interface. called from the core after a * SIOCSIFADDR ioctl, and from the bootup above. */static inte100_set_mac_address(struct net_device *dev, void *p){	struct net_local *np = (struct net_local *)dev->priv;	struct sockaddr *addr = p;	int i;	spin_lock(&np->lock); /* preemption protection */	/* remember it */	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);	/* Write it to the hardware.	 * Note the way the address is wrapped:	 * *R_NETWORK_SA_0 = a0_0 | (a0_1 << 8) | (a0_2 << 16) | (a0_3 << 24);	 * *R_NETWORK_SA_1 = a0_4 | (a0_5 << 8);	 */		*R_NETWORK_SA_0 = dev->dev_addr[0] | (dev->dev_addr[1] << 8) |		(dev->dev_addr[2] << 16) | (dev->dev_addr[3] << 24);	*R_NETWORK_SA_1 = dev->dev_addr[4] | (dev->dev_addr[5] << 8);	*R_NETWORK_SA_2 = 0;	/* show it in the log as well */	printk(KERN_INFO "%s: changed MAC to ", dev->name);	for (i = 0; i < 5; i++)		printk("%02X:", dev->dev_addr[i]);	printk("%02X\n", dev->dev_addr[i]);	spin_unlock(&np->lock);	return 0;}/* * 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 inte100_open(struct net_device *dev){	unsigned long flags;	/* enable the MDIO output pin */	*R_NETWORK_MGM_CTRL = IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable);	*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);		/* clear dma0 and 1 eop and descr irq masks */	*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);	/* Reset and wait for the DMA channels */	RESET_DMA(NETWORK_TX_DMA_NBR);	RESET_DMA(NETWORK_RX_DMA_NBR);	WAIT_DMA(NETWORK_TX_DMA_NBR);	WAIT_DMA(NETWORK_RX_DMA_NBR);	/* Initialise the etrax network controller */	/* allocate the irq corresponding to the receiving DMA */	if (request_irq(NETWORK_DMA_RX_IRQ_NBR, e100rxtx_interrupt, 0,			cardname, (void *)dev)) {		goto grace_exit0;	}	/* allocate the irq corresponding to the transmitting DMA */	if (request_irq(NETWORK_DMA_TX_IRQ_NBR, e100rxtx_interrupt, 0,			cardname, (void *)dev)) {		goto grace_exit1;	}	/* allocate the irq corresponding to the network errors etc */	if (request_irq(NETWORK_STATUS_IRQ_NBR, e100nw_interrupt, 0,			cardname, (void *)dev)) {		goto grace_exit2;	}	/* give the HW an idea of what MAC address we want */	*R_NETWORK_SA_0 = dev->dev_addr[0] | (dev->dev_addr[1] << 8) |		(dev->dev_addr[2] << 16) | (dev->dev_addr[3] << 24);	*R_NETWORK_SA_1 = dev->dev_addr[4] | (dev->dev_addr[5] << 8);	*R_NETWORK_SA_2 = 0;#if 0	/* use promiscuous mode for testing */	*R_NETWORK_GA_0 = 0xffffffff;	*R_NETWORK_GA_1 = 0xffffffff;	*R_NETWORK_REC_CONFIG = 0xd; /* broadcast rec, individ. rec, ma0 enabled */#else	SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, broadcast, receive);	SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, ma0, enable);	SETF(network_rec_config_shadow, R_NETWORK_REC_CONFIG, duplex, full_duplex);	*R_NETWORK_REC_CONFIG = network_rec_config_shadow;#endif	*R_NETWORK_GEN_CONFIG =		IO_STATE(R_NETWORK_GEN_CONFIG, phy,    mii_clk) |		IO_STATE(R_NETWORK_GEN_CONFIG, enable, on);	SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr);	SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, delay, none);	SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, cancel, dont);	SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, cd, enable);	SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, retry, enable);	SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, pad, enable);	SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, crc, enable);	*R_NETWORK_TR_CTRL = network_tr_ctrl_shadow;	save_flags(flags);	cli();	/* enable the irq's for ethernet DMA */	*R_IRQ_MASK2_SET =		IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set) |		IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set);	*R_IRQ_MASK0_SET =		IO_STATE(R_IRQ_MASK0_SET, overrun,       set) |		IO_STATE(R_IRQ_MASK0_SET, underrun,      set) |		IO_STATE(R_IRQ_MASK0_SET, excessive_col, set);	/* make sure the irqs are cleared */	*R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);	*R_DMA_CH1_CLR_INTR = IO_STATE(R_DMA_CH1_CLR_INTR, clr_eop, do);	/* make sure the rec and transmit error counters are cleared */	(void)*R_REC_COUNTERS;  /* dummy read */	(void)*R_TR_COUNTERS;   /* dummy read */	/* start the receiving DMA channel so we can receive packets from now on */	*R_DMA_CH1_FIRST = virt_to_phys(myNextRxDesc);	*R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, start);	/* Set up transmit DMA channel so it can be restarted later */        	*R_DMA_CH0_FIRST = 0;	*R_DMA_CH0_DESCR = virt_to_phys(myLastTxDesc);	restore_flags(flags);		/* Probe for transceiver */	if (e100_probe_transceiver())		goto grace_exit3;	/* Start duplex/speed timers */	add_timer(&speed_timer);	add_timer(&duplex_timer);	/* We are now ready to accept transmit requeusts from	 * the queueing layer of the networking.	 */	netif_start_queue(dev);	return 0;grace_exit3:	free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev);grace_exit2:	free_irq(NETWORK_DMA_TX_IRQ_NBR, (void *)dev);grace_exit1:	free_irq(NETWORK_DMA_RX_IRQ_NBR, (void *)dev);grace_exit0:	return -EAGAIN;}static voidgeneric_check_speed(void){	unsigned long data;	data = e100_get_mdio_reg(MDIO_ADVERTISMENT_REG);	if ((data & MDIO_ADVERT_100_FD) ||	    (data & MDIO_ADVERT_100_HD))		current_speed = 100;	else		current_speed = 10;}static voidtdk_check_speed(void){	unsigned long data;	data = e100_get_mdio_reg(MDIO_TDK_DIAGNOSTIC_REG);	current_speed = (data & MDIO_TDK_DIAGNOSTIC_RATE ? 100 : 10);}static voidbroadcom_check_speed(void){	unsigned long data;	data = e100_get_mdio_reg(MDIO_AUX_CTRL_STATUS_REG);	current_speed = (data & MDIO_BC_SPEED ? 100 : 10);}static voide100_check_speed(unsigned long dummy){	static int led_initiated = 0;	unsigned long data;	int old_speed = current_speed;	data = e100_get_mdio_reg(MDIO_BASE_STATUS_REG);	if (!(data & MDIO_LINK_UP_MASK)) {		current_speed = 0;	} else {		transceiver->check_speed();	}		if ((old_speed != current_speed) || !led_initiated) {		led_initiated = 1;		e100_set_network_leds(NO_NETWORK_ACTIVITY);	}	/* Reinitialize the timer. */	speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;	add_timer(&speed_timer);}static voide100_negotiate(void){	unsigned short data = e100_get_mdio_reg(MDIO_ADVERTISMENT_REG);	/* Discard old speed and duplex settings */	data &= ~(MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | 	          MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD);  	switch (current_speed_selection) {		case 10 :			if (current_duplex == full)				data |= MDIO_ADVERT_10_FD;			else if (current_duplex == half)				data |= MDIO_ADVERT_10_HD;			else				data |= MDIO_ADVERT_10_HD |  MDIO_ADVERT_10_FD;			break;		case 100 :			 if (current_duplex == full)				data |= MDIO_ADVERT_100_FD;			else if (current_duplex == half)				data |= MDIO_ADVERT_100_HD;			else				data |= MDIO_ADVERT_100_HD |  MDIO_ADVERT_100_FD;			break;		case 0 : /* Auto */			 if (current_duplex == full)				data |= MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD;			else if (current_duplex == half)				data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_10_HD;			else				data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD;			break;		default : /* assume autoneg speed and duplex */			data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | 			        MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD;	}	e100_set_mdio_reg(MDIO_ADVERTISMENT_REG, data);	/* Renegotiate with link partner */	data = e100_get_mdio_reg(MDIO_BASE_CONTROL_REG);	data |= MDIO_BC_NEGOTIATE;	e100_set_mdio_reg(MDIO_BASE_CONTROL_REG, data);}static voide100_set_speed(unsigned long speed){	if (speed != current_speed_selection) {		current_speed_selection = speed;		e100_negotiate();	}}static voide100_check_duplex(unsigned long dummy){	int old_duplex = full_duplex;	transceiver->check_duplex();	if (old_duplex != full_duplex) {		/* Duplex changed */		SETF(network_rec_config_shadow, R_NETWORK_REC_CONFIG, duplex, full_duplex);		*R_NETWORK_REC_CONFIG = network_rec_config_shadow;	}	/* Reinitialize the timer. */	duplex_timer.expires = jiffies + NET_DUPLEX_CHECK_INTERVAL;	add_timer(&duplex_timer);}static voidgeneric_check_duplex(void){	unsigned long data;	data = e100_get_mdio_reg(MDIO_ADVERTISMENT_REG);	if ((data & MDIO_ADVERT_100_FD) ||	    (data & MDIO_ADVERT_10_FD))		full_duplex = 1;

⌨️ 快捷键说明

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