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

📄 rtl8169.c

📁 F:worksip2440a board可启动u-boot-like.tar.gz F:worksip2440a board可启动u-boot-like.tar.gz
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************SEND - Transmit a frame***************************************************************************/static int rtl_send(struct eth_device *dev, volatile void *packet, int length){	/* send the packet to destination */	u32 to;	u8 *ptxb;	int entry = tpc->cur_tx % NUM_TX_DESC;	u32 len = length;#ifdef DEBUG_RTL8169_TX	int stime = currticks();	printf ("%s\n", __FUNCTION__);	printf("sending %d bytes\n", len);#endif	ioaddr = dev->iobase;	/* point to the current txb incase multiple tx_rings are used */	ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE];	memcpy(ptxb, (char *)packet, (int)length);	while (len < ETH_ZLEN)		ptxb[len++] = '\0';	tpc->TxDescArray[entry].buf_addr = virt_to_bus(ptxb);	if (entry != (NUM_TX_DESC - 1)) {		tpc->TxDescArray[entry].status =		    (OWNbit | FSbit | LSbit) | ((len > ETH_ZLEN) ?						len : ETH_ZLEN);	} else {		tpc->TxDescArray[entry].status =		    (OWNbit | EORbit | FSbit | LSbit) |		    ((len > ETH_ZLEN) ? length : ETH_ZLEN);	}	RTL_W8(TxPoll, 0x40);	/* set polling bit */	tpc->cur_tx++;	to = currticks() + TX_TIMEOUT;	while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to));	/* wait */	if (currticks() >= to) {#ifdef DEBUG_RTL8169_TX		puts ("tx timeout/error\n");		printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);#endif		return 0;	} else {#ifdef DEBUG_RTL8169_TX		puts("tx done\n");#endif		return length;	}}static void rtl8169_set_rx_mode(struct eth_device *dev){	u32 mc_filter[2];	/* Multicast hash filter */	int rx_mode;	u32 tmp = 0;#ifdef DEBUG_RTL8169	printf ("%s\n", __FUNCTION__);#endif	/* IFF_ALLMULTI */	/* Too many to filter perfectly -- accept all multicasts. */	rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;	mc_filter[1] = mc_filter[0] = 0xffffffff;	tmp = rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) &				   rtl_chip_info[tpc->chipset].RxConfigMask);	RTL_W32(RxConfig, tmp);	RTL_W32(MAR0 + 0, mc_filter[0]);	RTL_W32(MAR0 + 4, mc_filter[1]);}static void rtl8169_hw_start(struct eth_device *dev){	u32 i;#ifdef DEBUG_RTL8169	int stime = currticks();	printf ("%s\n", __FUNCTION__);#endif#if 0	/* Soft reset the chip. */	RTL_W8(ChipCmd, CmdReset);	/* Check that the chip has finished the reset. */	for (i = 1000; i > 0; i--) {		if ((RTL_R8(ChipCmd) & CmdReset) == 0)			break;		else			udelay(10);	}#endif	RTL_W8(Cfg9346, Cfg9346_Unlock);	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);	RTL_W8(EarlyTxThres, EarlyTxThld);	/* For gigabit rtl8169 */	RTL_W16(RxMaxSize, RxPacketMaxSize);	/* Set Rx Config register */	i = rtl8169_rx_config | (RTL_R32(RxConfig) &				 rtl_chip_info[tpc->chipset].RxConfigMask);	RTL_W32(RxConfig, i);	/* Set DMA burst size and Interframe Gap Time */	RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |				(InterFrameGap << TxInterFrameGapShift));	tpc->cur_rx = 0;	RTL_W32(TxDescStartAddr, virt_to_le32desc(tpc->TxDescArray));	RTL_W32(RxDescStartAddr, virt_to_le32desc(tpc->RxDescArray));	RTL_W8(Cfg9346, Cfg9346_Lock);	udelay(10);	RTL_W32(RxMissed, 0);	rtl8169_set_rx_mode(dev);	/* no early-rx interrupts */	RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);#ifdef DEBUG_RTL8169	printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);#endif}static void rtl8169_init_ring(struct eth_device *dev){	int i;#ifdef DEBUG_RTL8169	int stime = currticks();	printf ("%s\n", __FUNCTION__);#endif	tpc->cur_rx = 0;	tpc->cur_tx = 0;	tpc->dirty_tx = 0;	memset(tpc->TxDescArray, 0x0, NUM_TX_DESC * sizeof(struct TxDesc));	memset(tpc->RxDescArray, 0x0, NUM_RX_DESC * sizeof(struct RxDesc));	for (i = 0; i < NUM_TX_DESC; i++) {		tpc->Tx_skbuff[i] = &txb[i];	}	for (i = 0; i < NUM_RX_DESC; i++) {		if (i == (NUM_RX_DESC - 1))			tpc->RxDescArray[i].status =			    (OWNbit | EORbit) + RX_BUF_SIZE;		else			tpc->RxDescArray[i].status = OWNbit + RX_BUF_SIZE;		tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE];		tpc->RxDescArray[i].buf_addr =		    virt_to_bus(tpc->RxBufferRing[i]);	}#ifdef DEBUG_RTL8169	printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);#endif}/**************************************************************************RESET - Finish setting up the ethernet interface***************************************************************************/static void rtl_reset(struct eth_device *dev, bd_t *bis){	int i;	u8 diff;	u32 TxPhyAddr, RxPhyAddr;#ifdef DEBUG_RTL8169	int stime = currticks();	printf ("%s\n", __FUNCTION__);#endif	tpc->TxDescArrays = tx_ring;	if (tpc->TxDescArrays == 0)		puts("Allot Error");	/* Tx Desscriptor needs 256 bytes alignment; */	TxPhyAddr = virt_to_bus(tpc->TxDescArrays);	diff = 256 - (TxPhyAddr - ((TxPhyAddr >> 8) << 8));	TxPhyAddr += diff;	tpc->TxDescArray = (struct TxDesc *) (tpc->TxDescArrays + diff);	tpc->RxDescArrays = rx_ring;	/* Rx Desscriptor needs 256 bytes alignment; */	RxPhyAddr = virt_to_bus(tpc->RxDescArrays);	diff = 256 - (RxPhyAddr - ((RxPhyAddr >> 8) << 8));	RxPhyAddr += diff;	tpc->RxDescArray = (struct RxDesc *) (tpc->RxDescArrays + diff);	if (tpc->TxDescArrays == NULL || tpc->RxDescArrays == NULL) {		puts("Allocate RxDescArray or TxDescArray failed\n");		return;	}	rtl8169_init_ring(dev);	rtl8169_hw_start(dev);	/* Construct a perfect filter frame with the mac address as first match	 * and broadcast for all others */	for (i = 0; i < 192; i++)		txb[i] = 0xFF;	txb[0] = dev->enetaddr[0];	txb[1] = dev->enetaddr[1];	txb[2] = dev->enetaddr[2];	txb[3] = dev->enetaddr[3];	txb[4] = dev->enetaddr[4];	txb[5] = dev->enetaddr[5];#ifdef DEBUG_RTL8169	printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);#endif}/**************************************************************************HALT - Turn off ethernet interface***************************************************************************/static void rtl_halt(struct eth_device *dev){	int i;#ifdef DEBUG_RTL8169	printf ("%s\n", __FUNCTION__);#endif	ioaddr = dev->iobase;	/* Stop the chip's Tx and Rx DMA processes. */	RTL_W8(ChipCmd, 0x00);	/* Disable interrupts by clearing the interrupt mask. */	RTL_W16(IntrMask, 0x0000);	RTL_W32(RxMissed, 0);	tpc->TxDescArrays = NULL;	tpc->RxDescArrays = NULL;	tpc->TxDescArray = NULL;	tpc->RxDescArray = NULL;	for (i = 0; i < NUM_RX_DESC; i++) {		tpc->RxBufferRing[i] = NULL;	}}/**************************************************************************INIT - Look for an adapter, this routine's visible to the outside***************************************************************************/#define board_found 1#define valid_link 0static int rtl_init(struct eth_device *dev, bd_t *bis){	static int board_idx = -1;	static int printed_version = 0;	int i, rc;	int option = -1, Cap10_100 = 0, Cap1000 = 0;#ifdef DEBUG_RTL8169	printf ("%s\n", __FUNCTION__);#endif	ioaddr = dev->iobase;	board_idx++;	printed_version = 1;	/* point to private storage */	tpc = &tpx;	rc = rtl8169_init_board(dev);	if (rc)		return rc;	/* Get MAC address.  FIXME: read EEPROM */	for (i = 0; i < MAC_ADDR_LEN; i++)		dev->enetaddr[i] = RTL_R8(MAC0 + i);#ifdef DEBUG_RTL8169	printf("MAC Address");	for (i = 0; i < MAC_ADDR_LEN; i++)		printf(":%02x", dev->enetaddr[i]);	putc('\n');#endif#ifdef DEBUG_RTL8169	/* Print out some hardware info */	printf("%s: at ioaddr 0x%x\n", dev->name, ioaddr);#endif	/* if TBI is not endbled */	if (!(RTL_R8(PHYstatus) & TBI_Enable)) {		int val = mdio_read(PHY_AUTO_NEGO_REG);		option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];		/* Force RTL8169 in 10/100/1000 Full/Half mode. */		if (option > 0) {#ifdef DEBUG_RTL8169			printf("%s: Force-mode Enabled.\n", dev->name);#endif			Cap10_100 = 0, Cap1000 = 0;			switch (option) {			case _10_Half:				Cap10_100 = PHY_Cap_10_Half;				Cap1000 = PHY_Cap_Null;				break;			case _10_Full:				Cap10_100 = PHY_Cap_10_Full;				Cap1000 = PHY_Cap_Null;				break;			case _100_Half:				Cap10_100 = PHY_Cap_100_Half;				Cap1000 = PHY_Cap_Null;				break;			case _100_Full:				Cap10_100 = PHY_Cap_100_Full;				Cap1000 = PHY_Cap_Null;				break;			case _1000_Full:				Cap10_100 = PHY_Cap_Null;				Cap1000 = PHY_Cap_1000_Full;				break;			default:				break;			}			mdio_write(PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F));	/* leave PHY_AUTO_NEGO_REG bit4:0 unchanged */			mdio_write(PHY_1000_CTRL_REG, Cap1000);		} else {#ifdef DEBUG_RTL8169			printf("%s: Auto-negotiation Enabled.\n",			       dev->name);#endif			/* enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged */			mdio_write(PHY_AUTO_NEGO_REG,				   PHY_Cap_10_Half | PHY_Cap_10_Full |				   PHY_Cap_100_Half | PHY_Cap_100_Full |				   (val & 0x1F));			/* enable 1000 Full Mode */			mdio_write(PHY_1000_CTRL_REG, PHY_Cap_1000_Full);		}		/* Enable auto-negotiation and restart auto-nigotiation */		mdio_write(PHY_CTRL_REG,			   PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego);		udelay(100);		/* wait for auto-negotiation process */		for (i = 10000; i > 0; i--) {			/* check if auto-negotiation complete */			if (mdio_read(PHY_STAT_REG) & PHY_Auto_Neco_Comp) {				udelay(100);				option = RTL_R8(PHYstatus);				if (option & _1000bpsF) {#ifdef DEBUG_RTL8169					printf("%s: 1000Mbps Full-duplex operation.\n",					     dev->name);#endif				} else {#ifdef DEBUG_RTL8169					printf					    ("%s: %sMbps %s-duplex operation.\n",					     dev->name,					     (option & _100bps) ? "100" :					     "10",					     (option & FullDup) ? "Full" :					     "Half");#endif				}				break;			} else {				udelay(100);			}		}		/* end for-loop to wait for auto-negotiation process */	} else {		udelay(100);#ifdef DEBUG_RTL8169		printf		    ("%s: 1000Mbps Full-duplex operation, TBI Link %s!\n",		     dev->name,		     (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed");#endif	}	return 1;}int rtl8169_initialize(bd_t *bis){	pci_dev_t devno;	int card_number = 0;	struct eth_device *dev;	u32 iobase;	int idx=0;	while(1){		/* Find RTL8169 */		if ((devno = pci_find_devices(supported, idx++)) < 0)			break;		pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase);		iobase &= ~0xf;		debug ("rtl8169: REALTEK RTL8169 @0x%x\n", iobase);		dev = (struct eth_device *)malloc(sizeof *dev);		sprintf (dev->name, "RTL8169#%d", card_number);		dev->priv = (void *) devno;		dev->iobase = (int)bus_to_phys(iobase);		dev->init = rtl_reset;		dev->halt = rtl_halt;		dev->send = rtl_send;		dev->recv = rtl_recv;		eth_register (dev);		rtl_init(dev, bis);		card_number++;	}	return card_number;}#endif

⌨️ 快捷键说明

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