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

📄 ethernet.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
struct transceiver_ops transceivers[] = {	{0x1018, broadcom_check_speed, broadcom_check_duplex},  /* Broadcom */	{0xC039, tdk_check_speed, tdk_check_duplex},            /* TDK 2120 */	{0x039C, tdk_check_speed, tdk_check_duplex},            /* TDK 2120C */	{0x0000, generic_check_speed, generic_check_duplex}     /* Generic, must be last */};#define tx_done(dev) (*R_DMA_CH0_CMD == 0)/* * Check for a network adaptor of this type, and return '0' if one exists. * 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(struct net_device *dev){	int i;	printk(KERN_INFO	       "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2001 Axis Communications AB\n");	dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */	printk(KERN_INFO "%s initialized\n", dev->name);	/* make Linux aware of the new hardware  */	if (!dev) {		printk(KERN_WARNING "%s: dev == NULL. Should this happen?\n",		       cardname);		dev = init_etherdev(dev, sizeof(struct net_local));		if (!dev)			panic("init_etherdev failed\n");	}	/* setup generic handlers and stuff in the dev struct */	ether_setup(dev);	/* make room for the local structure containing stats etc */	dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);	if (dev->priv == NULL)		return -ENOMEM;	memset(dev->priv, 0, sizeof(struct net_local));	/* 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->tx_timeout         = e100_tx_timeout;	/* set the default MAC address */	e100_set_mac_address(dev, &default_mac);	/* 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];	/* 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 sockaddr *addr = p;	int i;	/* 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]);	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;	}	/*	 * Always allocate the DMA channels after the IRQ,	 * and clean up on failure.	 */	if (request_dma(NETWORK_TX_DMA_NBR, cardname)) {		goto grace_exit3;	}	if (request_dma(NETWORK_RX_DMA_NBR, cardname)) {		goto grace_exit4;	}	/* 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);	*R_NETWORK_TR_CTRL = 		IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr) |		IO_STATE(R_NETWORK_TR_CTRL, delay, none) |		IO_STATE(R_NETWORK_TR_CTRL, cancel, dont) |		IO_STATE(R_NETWORK_TR_CTRL, cd, enable) |		IO_STATE(R_NETWORK_TR_CTRL, retry, enable) |		IO_STATE(R_NETWORK_TR_CTRL, pad, enable) |		IO_STATE(R_NETWORK_TR_CTRL, crc, enable);	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_exit4;	/* 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_exit4:	free_dma(NETWORK_TX_DMA_NBR);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;

⌨️ 快捷键说明

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