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

📄 r8169.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 2 页
字号:
static int r8169_poll(struct nic *nic){	/* return true if there's an ethernet packet ready to read */	/* nic->packet should contain data on return */	/* nic->packetlen should contain length of data */	int cur_rx;	cur_rx = tpc->cur_rx;	if ((tpc->RxDescArray[cur_rx].status & OWNbit) == 0) {		if (!(tpc->RxDescArray[cur_rx].status & RxRES)) {			nic->packetlen = (int) (tpc->RxDescArray[cur_rx].						status & 0x00001FFF) - 4;			memcpy(nic->packet, tpc->RxBufferRing[cur_rx],			       nic->packetlen);			if (cur_rx == NUM_RX_DESC - 1)				tpc->RxDescArray[cur_rx].status =				    (OWNbit | EORbit) + RX_BUF_SIZE;			else				tpc->RxDescArray[cur_rx].status =				    OWNbit + RX_BUF_SIZE;			tpc->RxDescArray[cur_rx].buf_addr =			    virt_to_bus(tpc->RxBufferRing[cur_rx]);		} else			printf("Error Rx");		cur_rx = (cur_rx + 1) % NUM_RX_DESC;		tpc->cur_rx = cur_rx;		return 1;	}	tpc->cur_rx = cur_rx;	return (0);		/* initially as this is called to flush the input */}#define HZ 1000/**************************************************************************TRANSMIT - Transmit a frame***************************************************************************/static void r8169_transmit(struct nic *nic, const char *d,	/* Destination */			    unsigned int t,	/* Type */			    unsigned int s,	/* size */			    const char *p){				/* Packet */	/* send the packet to destination */	u16 nstype;	u32 to;	u8 *ptxb;	int entry = tpc->cur_tx % NUM_TX_DESC;	/* point to the current txb incase multiple tx_rings are used */	ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE];	memcpy(ptxb, d, ETH_ALEN);	memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN);	nstype = htons((u16) t);	memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2);	memcpy(ptxb + ETH_HLEN, p, s);	s += ETH_HLEN;	s &= 0x0FFF;	while (s < ETH_ZLEN)		ptxb[s++] = '\0';	tpc->TxDescArray[entry].buf_addr = virt_to_bus(ptxb);	if (entry != (NUM_TX_DESC - 1))		tpc->TxDescArray[entry].status =		    (OWNbit | FSbit | LSbit) | ((s > ETH_ZLEN) ?						s : ETH_ZLEN);	else		tpc->TxDescArray[entry].status =		    (OWNbit | EORbit | FSbit | LSbit) |		    ((s > ETH_ZLEN) ? s : 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) {		printf("TX Time Out");	}}static void rtl8169_set_rx_mode(struct nic *nic __unused){	u32 mc_filter[2];	/* Multicast hash filter */	int rx_mode;	u32 tmp = 0;	/* 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 nic *nic){	u32 i;	/* 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);	}	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(nic);	/* no early-rx interrupts */	RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);}static void rtl8169_init_ring(struct nic *nic __unused){	int i;	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]);	}}/**************************************************************************RESET - Finish setting up the ethernet interface***************************************************************************/static void r8169_reset(struct nic *nic){	int i;	u8 diff;	u32 TxPhyAddr, RxPhyAddr;	tpc->TxDescArrays = tx_ring; 	if (tpc->TxDescArrays == 0)		printf("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) {		printf("Allocate RxDescArray or TxDescArray failed\n");		return;	}	rtl8169_init_ring(nic);	rtl8169_hw_start(nic);	/* 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] = nic->node_addr[0];	txb[1] = nic->node_addr[1];	txb[2] = nic->node_addr[2];	txb[3] = nic->node_addr[3];	txb[4] = nic->node_addr[4];	txb[5] = nic->node_addr[5];}/**************************************************************************DISABLE - Turn off ethernet interface***************************************************************************/static void r8169_disable(struct dev *dev __unused){	int i;	/* 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;	}}/**************************************************************************PROBE - Look for an adapter, this routine's visible to the outside***************************************************************************/#define board_found 1#define valid_link 0static int r8169_probe(struct dev *dev, struct pci_device *pci){	struct nic *nic = (struct nic *) dev;	static int board_idx = -1;	static int printed_version = 0;	int i, rc;	int option = -1, Cap10_100 = 0, Cap1000 = 0;	/* BASE is used throughout to address the card */	printf("\n");	printf	    ("r8169.c: %s, %s\n", drv_version, drv_date);	printf("%s: Probing for Vendor=%hX   Device=%hX, %s\n", pci->name,	       pci->vendor, pci->dev_id);	board_idx++;	printed_version = 1;	/* point to private storage */	tpc = &tpx;	rc = rtl8169_init_board(pci);	if (rc)		return rc;	// Get MAC address.  FIXME: read EEPROM	for (i = 0; i < MAC_ADDR_LEN; i++)		nic->node_addr[i] = RTL_R8(MAC0 + i);	printf("%s: Identified chip type is '%s'.\n", pci->name,	       rtl_chip_info[tpc->chipset].name);	/* Print out some hardware info */	printf("%s%s: %! at ioaddr %hX\n", pci->name, nic->node_addr, ioaddr);	// 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) {			printf("%s: Force-mode Enabled.\n", pci->name);			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 {			printf("%s: Auto-negotiation Enabled.\n",			       pci->name);			// 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) {					printf					    ("%s: 1000Mbps Full-duplex operation.\n",					     pci->name);				} else {					printf					    ("%s: %sMbps %s-duplex operation.\n",					     pci->name,					     (option & _100bps) ? "100" :					     "10",					     (option & FullDup) ? "Full" :					     "Half");				}				break;			} else {				udelay(100);			}		}		// end for-loop to wait for auto-negotiation process	} else {		udelay(100);		printf		    ("%s: 1000Mbps Full-duplex operation, TBI Link %s!\n",		     pci->name,		     (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed");	}	r8169_reset(nic);	/* point to NIC specific routines */	dev->disable = r8169_disable;	nic->poll = r8169_poll;	nic->transmit = r8169_transmit;	return 1;}static struct pci_id r8169_nics[] = {	PCI_ROM(0x10ec, 0x8169, "r8169", "RealTek RTL8169 Gigabit Ethernet"),};static struct pci_driver r8169_driver __pci_driver = {	.type = NIC_DRIVER,	.name = "r8169/PCI",	.probe = r8169_probe,	.ids = r8169_nics,	.id_count = sizeof(r8169_nics) / sizeof(r8169_nics[0]),	.class = 0,};

⌨️ 快捷键说明

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