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

📄 enet.c

📁 uboot200903最新版本的通用uboot
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* Find ethernet controller on the PCI bus */	if ((devno =	     pci_find_device (PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905C,			      0)) < 0) {		PRINTF ("Error: Cannot find the ethernet device on the PCI bus\n");		goto Done;	}	if (s) {		unsigned long base = atoi (s);		pci_write_config_dword (devno, PCI_BASE_ADDRESS_0,					base | 0x01);	}	ret = pci_read_config_dword (devno, PCI_BASE_ADDRESS_0, &eth_iobase);	eth_iobase &= ~0xf;	PRINTF ("eth: 3Com Found at Address: 0x%x\n", eth_iobase);	pci_write_config_dword (devno, PCI_COMMAND,				PCI_COMMAND_IO | PCI_COMMAND_MEMORY |				PCI_COMMAND_MASTER);	/* Check if I/O accesses and Bus Mastering are enabled */	ret = pci_read_config_dword (devno, PCI_COMMAND, &status);	if (!(status & PCI_COMMAND_IO)) {		printf ("Error: Cannot enable IO access.\n");		goto Done;	}	if (!(status & PCI_COMMAND_MEMORY)) {		printf ("Error: Cannot enable MEMORY access.\n");		goto Done;	}	if (!(status & PCI_COMMAND_MASTER)) {		printf ("Error: Cannot enable Bus Mastering.\n");		goto Done;	}	dev = (struct eth_device *) malloc (sizeof (*dev));	/*struct eth_device)); */	sprintf (dev->name, "3Com 3c920c#%d", card_number);	dev->iobase = eth_iobase;	dev->priv = (void *) devno;	dev->init = eth_3com_init;	dev->halt = eth_3com_halt;	dev->send = eth_3com_send;	dev->recv = eth_3com_recv;	eth_register (dev);/*	{ *//*	    char interrupt; *//*	    devno = pci_find_device(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905C, 0); *//*	    pci_read_config_byte(devno, PCI_INTERRUPT_LINE, &interrupt); *//*	    printf("Installing eth0 interrupt handler to %d\n", interrupt); *//*	    irq_install_handler(interrupt, eth_interrupt, dev); *//*	} */	card_number++;	/* Set the latency timer for value */	s = getenv ("3com_latency");	if (s) {		ret = pci_write_config_byte (devno, PCI_LATENCY_TIMER,					     (unsigned char) atoi (s));	} else		ret = pci_write_config_byte (devno, PCI_LATENCY_TIMER, 0x0a);	read_hw_addr (dev, bis);	/* get the MAC address from Window 2 */	/* Reset the ethernet controller */	PRINTF ("Issuing reset command....\n");	if (!issue_and_wait (dev, TotalReset)) {		printf ("Error: Cannot reset ethernet controller.\n");		goto Done;	} else		PRINTF ("Ethernet controller reset.\n");	/* allocate memory for rx and tx rings */	if (!(rx_ring = memalign (sizeof (struct rx_desc_3com) * NUM_RX_DESC, 16))) {		PRINTF ("Cannot allocate memory for RX_RING.....\n");		goto Done;	}	if (!(tx_ring = memalign (sizeof (struct tx_desc_3com) * NUM_TX_DESC, 16))) {		PRINTF ("Cannot allocate memory for TX_RING.....\n");		goto Done;	}Done:	return status;}static int eth_3com_init (struct eth_device *dev, bd_t * bis){	int i, status = 0;	int tx_cur, loop;	u16 status_enable, intr_enable;	struct descriptor *ias_cmd;	/* Determine what type of network the machine is connected to   */	/* presently drops the connect to 10Mbps                        */	if (!auto_negotiate (dev)) {		printf ("Error: Cannot determine network media.\n");		goto Done;	}	issue_and_wait (dev, TxReset);	issue_and_wait (dev, RxReset | 0x04);	/* Switch to register set 7 for normal use. */	EL3WINDOW (dev, 7);	/* Initialize Rx and Tx rings */	init_rx_ring (dev);	purge_tx_ring (dev);	ETH_CMD (dev, SetRxFilter | RxStation | RxBroadcast | RxProm);	issue_and_wait (dev, SetTxStart | 0x07ff);	/* Below sets which indication bits to be seen. */	status_enable =		SetStatusEnb | HostError | DownComplete | UpComplete | (1 <<									6);	ETH_CMD (dev, status_enable);	/* Below sets no bits are to cause an interrupt since this is just polling */	intr_enable = SetIntrEnb;/*	intr_enable = SetIntrEnb | (1<<9) | (1<<10) | (1<<6); */	ETH_CMD (dev, intr_enable);	ETH_OUTB (dev, 127, UpPoll);	/* Ack all pending events, and set active indicator mask */	ETH_CMD (dev, AckIntr | IntLatch | TxAvailable | RxEarly | IntReq);	ETH_CMD (dev, intr_enable);	/* Tell the adapter where the RX ring is located */	issue_and_wait (dev, UpStall);	/* Stall and set the UplistPtr          */	ETH_OUTL (dev, (u32) & rx_ring[rx_next], UpListPtr);	ETH_CMD (dev, RxEnable);	/* Enable the receiver.         */	issue_and_wait (dev, UpUnstall);	/* Send the Individual Address Setup frame */	tx_cur = tx_next;	tx_next = ((tx_next + 1) % NUM_TX_DESC);	ias_cmd = (struct descriptor *) &tx_ring[tx_cur];	ias_cmd->status = cpu_to_le32 (1 << 31);	/* set DnIndicate bit.                  */	ias_cmd->next = 0;	ias_cmd->addr = cpu_to_le32 ((u32) & bis->bi_enetaddr[0]);	ias_cmd->length = cpu_to_le32 (6 | LAST_FRAG);	/* Tell the adapter where the TX ring is located */	ETH_CMD (dev, TxEnable);	/* Enable transmitter.                  */	issue_and_wait (dev, DownStall);	/* Stall and set the DownListPtr.       */	ETH_OUTL (dev, (u32) & tx_ring[tx_cur], DownListPtr);	issue_and_wait (dev, DownUnstall);	for (i = 0; !(ETH_STATUS (dev) & DownComplete); i++) {		if (i >= TOUT_LOOP) {			PRINTF ("TX Ring status (Init):	0x%4x\n",				le32_to_cpu (tx_ring[tx_cur].status));			PRINTF ("ETH_STATUS: 0x%x\n", ETH_STATUS (dev));			goto Done;		}	}	if (ETH_STATUS (dev) & DownComplete) {	/* If DownLoad Complete ACK the bit       */		ETH_CMD (dev, AckIntr | DownComplete);	/* acknowledge the indication bit       */		issue_and_wait (dev, DownStall);	/* stall and clear DownListPtr          */		ETH_OUTL (dev, 0, DownListPtr);		issue_and_wait (dev, DownUnstall);	}	status = 1;Done:	return status;}int eth_3com_send (struct eth_device *dev, volatile void *packet, int length){	int i, status = 0;	int tx_cur;	if (length <= 0) {		PRINTF ("eth: bad packet size: %d\n", length);		goto Done;	}	tx_cur = tx_next;	tx_next = (tx_next + 1) % NUM_TX_DESC;	tx_ring[tx_cur].status = cpu_to_le32 (1 << 31);	/* set DnIndicate bit                   */	tx_ring[tx_cur].next = 0;	tx_ring[tx_cur].addr = cpu_to_le32 (((u32) packet));	tx_ring[tx_cur].length = cpu_to_le32 (length | LAST_FRAG);	/* Send the packet */	issue_and_wait (dev, DownStall);	/* stall and set the DownListPtr        */	ETH_OUTL (dev, (u32) & tx_ring[tx_cur], DownListPtr);	issue_and_wait (dev, DownUnstall);	for (i = 0; !(ETH_STATUS (dev) & DownComplete); i++) {		if (i >= TOUT_LOOP) {			PRINTF ("TX Ring status (send): 0x%4x\n",				le32_to_cpu (tx_ring[tx_cur].status));			goto Done;		}	}	if (ETH_STATUS (dev) & DownComplete) {	/* If DownLoad Complete ACK the bit       */		ETH_CMD (dev, AckIntr | DownComplete);	/* acknowledge the indication bit       */		issue_and_wait (dev, DownStall);	/* stall and clear DownListPtr          */		ETH_OUTL (dev, 0, DownListPtr);		issue_and_wait (dev, DownUnstall);	}	status = 1;Done:	return status;}void PrintPacket (uchar * packet, int length){	int loop;	uchar *ptr;	printf ("Printing packet of length %x.\n\n", length);	ptr = packet;	for (loop = 1; loop <= length; loop++) {		printf ("%2x ", *ptr++);		if ((loop % 40) == 0)			printf ("\n");	}}int eth_3com_recv (struct eth_device *dev){	u16 stat = 0;	u32 status;	int rx_prev, length = 0;	while (!(ETH_STATUS (dev) & UpComplete))	/* wait on receipt of packet        */		;	status = le32_to_cpu (rx_ring[rx_next].status);	/* packet status                */	while (status & (1 << 15)) {		/* A packet has been received */		if (status & (1 << 15)) {			/* A valid frame received  */			length = le32_to_cpu (rx_ring[rx_next].status) & 0x1fff;	/* length is in bits 0 - 12     */			/* Pass the packet up to the protocol layers */			NetReceive ((uchar *)				    le32_to_cpu (rx_ring[rx_next].addr),				    length);			rx_ring[rx_next].status = 0;	/* clear the status word        */			ETH_CMD (dev, AckIntr | UpComplete);			issue_and_wait (dev, UpUnstall);		} else if (stat & HostError) {			/* There was an error */			printf ("Rx error status:  0x%4x\n", stat);			init_rx_ring (dev);			goto Done;		}		rx_prev = rx_next;		rx_next = (rx_next + 1) % NUM_RX_DESC;		stat = ETH_STATUS (dev);	/* register status      */		status = le32_to_cpu (rx_ring[rx_next].status);	/* packet status        */	}Done:	return length;}void eth_3com_halt (struct eth_device *dev){	if (!(dev->iobase)) {		goto Done;	}	issue_and_wait (dev, DownStall);	/* shut down transmit and receive */	issue_and_wait (dev, UpStall);	issue_and_wait (dev, RxDisable);	issue_and_wait (dev, TxDisable);/*	free(tx_ring);				/###* release memory allocated to the DPD and UPD rings *//*	free(rx_ring); */Done:	return;}static void init_rx_ring (struct eth_device *dev){	int i;	PRINTF ("Initializing rx_ring. rx_buffer = %p\n", rx_buffer);	issue_and_wait (dev, UpStall);	for (i = 0; i < NUM_RX_DESC; i++) {		rx_ring[i].next =			cpu_to_le32 (((u32) &				      rx_ring[(i + 1) % NUM_RX_DESC]));		rx_ring[i].status = 0;		rx_ring[i].addr = cpu_to_le32 (((u32) & rx_buffer[i][0]));		rx_ring[i].length = cpu_to_le32 (PKTSIZE_ALIGN | LAST_FRAG);	}	rx_next = 0;}static void purge_tx_ring (struct eth_device *dev){	int i;	PRINTF ("Purging tx_ring.\n");	tx_next = 0;	for (i = 0; i < NUM_TX_DESC; i++) {		tx_ring[i].next = 0;		tx_ring[i].status = 0;		tx_ring[i].addr = 0;		tx_ring[i].length = 0;	}}static void read_hw_addr (struct eth_device *dev, bd_t * bis){	u8 hw_addr[ETH_ALEN];	unsigned int eeprom[0x40];	unsigned int checksum = 0;	int i, j, timer;	/* Read the station address from the EEPROM. */	EL3WINDOW (dev, 0);	for (i = 0; i < 0x40; i++) {		ETH_OUTW (dev, EEPROM_Read + i, Wn0EepromCmd);		/* Pause for at least 162 us. for the read to take place. */		for (timer = 10; timer >= 0; timer--) {			udelay (162);			if ((ETH_INW (dev, Wn0EepromCmd) & 0x8000) == 0)				break;		}		eeprom[i] = ETH_INW (dev, Wn0EepromData);	}	/* Checksum calculation.  I'm not sure about this part and there seems to be a bug on the 3com side of things */	for (i = 0; i < 0x21; i++)		checksum ^= eeprom[i];	checksum = (checksum ^ (checksum >> 8)) & 0xff;	if (checksum != 0xbb)		printf (" *** INVALID EEPROM CHECKSUM %4.4x *** \n",			checksum);	for (i = 0, j = 0; i < 3; i++) {		hw_addr[j++] = (u8) ((eeprom[i + 10] >> 8) & 0xff);		hw_addr[j++] = (u8) (eeprom[i + 10] & 0xff);	}	/*  MAC Address is in window 2, write value from EEPROM to window 2 */	EL3WINDOW (dev, 2);	for (i = 0; i < 6; i++)		ETH_OUTB (dev, hw_addr[i], i);	for (j = 0; j < ETH_ALEN; j += 2) {		hw_addr[j] = (u8) (ETH_INW (dev, j) & 0xff);		hw_addr[j + 1] = (u8) ((ETH_INW (dev, j) >> 8) & 0xff);	}	for (i = 0; i < ETH_ALEN; i++) {		if (hw_addr[i] != bis->bi_enetaddr[i]) {/*			printf("Warning: HW address don't match:\n"); *//*			printf("Address in 3Com Window 2 is	    " *//*			       "%02X:%02X:%02X:%02X:%02X:%02X\n", *//*			       hw_addr[0], hw_addr[1], hw_addr[2], *//*			       hw_addr[3], hw_addr[4], hw_addr[5]); *//*			printf("Address used by U-Boot is " *//*			       "%02X:%02X:%02X:%02X:%02X:%02X\n", *//*			       bis->bi_enetaddr[0], bis->bi_enetaddr[1],  *//*			       bis->bi_enetaddr[2], bis->bi_enetaddr[3],  *//*			       bis->bi_enetaddr[4], bis->bi_enetaddr[5]); *//*			goto Done; */			char buffer[256];			if (bis->bi_enetaddr[0] == 0			    && bis->bi_enetaddr[1] == 0			    && bis->bi_enetaddr[2] == 0			    && bis->bi_enetaddr[3] == 0			    && bis->bi_enetaddr[4] == 0			    && bis->bi_enetaddr[5] == 0) {				sprintf (buffer,					 "%02X:%02X:%02X:%02X:%02X:%02X",					 hw_addr[0], hw_addr[1], hw_addr[2],					 hw_addr[3], hw_addr[4], hw_addr[5]);				setenv ("ethaddr", buffer);			}		}	}	for (i = 0; i < ETH_ALEN; i++)		dev->enetaddr[i] = hw_addr[i];Done:	return;}

⌨️ 快捷键说明

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