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

📄 realtekr1000.cpp

📁 Mac OS X 下的网卡驱动
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	if (!tx_descMd || tx_descMd->prepare() != kIOReturnSuccess)	{		DLog("Couldn't allocate physical memory for tx_desc\n");		return false;	}		txdesc_space = tx_descMd->getBytesNoCopy();	txdesc_phy_dma_addr = tx_descMd->getPhysicalSegment(0, &len);			sizeof_rxdesc_space = NUM_RX_DESC * sizeof(RxDesc) + 256;	rx_descMd = IOBufferMemoryDescriptor::withOptions(kIOMemoryPhysicallyContiguous,														sizeof_rxdesc_space,														PAGE_SIZE);		if (!rx_descMd || rx_descMd->prepare() != kIOReturnSuccess)	{		DLog("Couldn't allocate physical memory for rx_desc\n");		return false;	}		rxdesc_space = rx_descMd->getBytesNoCopy();	rxdesc_phy_dma_addr = rx_descMd->getPhysicalSegment(0, &len);	TxDescArray = reinterpret_cast<TxDesc *>(txdesc_space);	RxDescArray = reinterpret_cast<RxDesc *>(rxdesc_space);	for(int i = 0; i < NUM_RX_DESC; i++)	{		Rx_dbuff[i] = 0;		Rx_skbuff_Md[i] = IOBufferMemoryDescriptor::withOptions(kIOMemoryPhysicallyContiguous,														MAX_RX_SKBDATA_SIZE,														PAGE_SIZE);		if (!Rx_skbuff_Md[i] || Rx_skbuff_Md[i]->prepare() != kIOReturnSuccess)		{			DLog("Couldn't allocate physical memory for Rx_dbuff, step %d\n", i);			return false;		}		Rx_dbuff[i] = static_cast<uchar *>(Rx_skbuff_Md[i]->getBytesNoCopy());		if (!Rx_dbuff[i])		{			DLog("Pointer in NULL, step %d\n", i);			return false;		}				IOByteCount len;		Rx_skbuff_Dma[i] = Rx_skbuff_Md[i]->getPhysicalSegment(0, &len);		RxDescArray[i].status = 0;		RxDescArray[i].vlan_tag = 0;		/*Rx_skbuff[i] = NULL;//allocatePacket(MAX_RX_SKBDATA_SIZE);		Rx_skbuff_Dma[i] = static_cast<IOPhysicalAddress>(mbuf_data_to_physical(mbuf_data(Rx_skbuff[i])));*/					}		//Ring initialization	for(int i = 0; i < NUM_TX_DESC; i++)	{		/*Tx_skbuff[i] = NULL;		TxDescArray[i].status = 0;*/		//Tx_skbuff_Md[i] = NULL;		Tx_dbuff[i] = NULL;		Tx_skbuff_Md[i] = IOBufferMemoryDescriptor::withOptions(kIOMemoryPhysicallyContiguous,																MAX_TX_SKBDATA_SIZE,																PAGE_SIZE);		if (!Tx_skbuff_Md[i] || Tx_skbuff_Md[i]->prepare() != kIOReturnSuccess)		{			DLog("Couldn't allocate physical memory for Tx_dbuff, step %d\n", i);			return false;		}		Tx_dbuff[i] = static_cast<uchar *>(Tx_skbuff_Md[i]->getBytesNoCopy());		if (!Tx_dbuff[i])		{			DLog("Pointer in NULL, step %d\n", i);			return false;		}		IOByteCount len;		Tx_skbuff_Dma[i] = static_cast<IOPhysicalAddress>(Tx_skbuff_Md[i]->getPhysicalSegment(0, &len));		TxDescArray[i].status = 0;		TxDescArray[i].vlan_tag = 0;		TxDescArray[i].buf_addr = OSSwapHostToLittleInt32(Tx_skbuff_Dma[i]);		TxDescArray[i].buf_Haddr = 0;	}		for(int i = 0; i < NUM_RX_DESC; i++)	{		if (i == (NUM_RX_DESC - 1))		{			RxDescArray[i].status = OSSwapHostToLittleInt32((OWNbit | EORbit) | static_cast<unsigned long>(hw_rx_pkt_len));		}		else		{			RxDescArray[i].status = OSSwapHostToLittleInt32(OWNbit | static_cast<unsigned long>(hw_rx_pkt_len));		}				RxDescArray[i].buf_addr = OSSwapHostToLittleInt32(Rx_skbuff_Dma[i]);		RxDescArray[i].buf_Haddr = 0;	}	return true;}void RealtekR1000::FreeDescriptorsMemory(){	R1000TxClear();	if (tx_descMd)	{		tx_descMd->complete();		tx_descMd->release();		tx_descMd = NULL;	}		if (rx_descMd)	{		rx_descMd->complete();		rx_descMd->release();		rx_descMd = NULL;	}		for(int i = 0; i < NUM_RX_DESC; i++)	{		if (Rx_skbuff_Md[i])		{			Rx_skbuff_Md[i]->complete();			Rx_skbuff_Md[i]->release();			Rx_skbuff_Md[i] = NULL;		}	}		for(int i = 0; i < NUM_TX_DESC; i++)	{		if (Tx_skbuff_Md[i])		{			Tx_skbuff_Md[i]->complete();			Tx_skbuff_Md[i]->release();			Tx_skbuff_Md[i] = NULL;		}	}	}	bool RealtekR1000::R1000InitEventSources(IOService *provider){	DLog("RealtekR1000::R1000InitEventSources()\n");		IOWorkLoop *loop = getWorkLoop(); //Needed, cause may be called before WorkLoop creation	//Sanity check	if (!loop)	{		DLog("::R1000InitEventSources: Could not getWorkLoop.\n");		return false;	}		transmitQueue = getOutputQueue();		if (!transmitQueue)	{ 		DLog("::R1000InitEventSources: Could not getOutputQueue.\n");		return false;	}		// we need to see what else is listening on this interrupt to allow multiple devices to function	// or else we break other things, like other NIC's and what not	/*	int msi_index = -1;	int intr_index = 0, intr_type = 0;	IOReturn intr_ret;	while (true)	{		intr_ret = provider->getInterruptType(intr_index, &intr_type);		if (intr_ret != kIOReturnSuccess) break;		if (intr_type & kIOInterruptTypePCIMessaged) msi_index = intr_index;		intr_index++;			}		DLog("RTL1000: Got interrupt index of '%d'.\n", msi_index);	// set to zero just in case we didnt find anything	if(!msi_index) { msi_index = 0; }	DLog("RTL1000: Got interrupt index of '%d'.\n", msi_index);		intSource = IOInterruptEventSource::interruptEventSource(this, 					OSMemberFunctionCast(IOInterruptEventSource::Action, this, &RealtekR1000::R1000Interrupt),					pciDev, msi_index);							// check for some type of fuckup with msi_index = 0   */	intSource = IOInterruptEventSource::interruptEventSource(this, 							OSMemberFunctionCast(IOInterruptEventSource::Action, this, &RealtekR1000::R1000Interrupt),								pciDev);							//Adding interrupt to our workloop event sources	if (!intSource || loop->addEventSource(intSource) != kIOReturnSuccess)	{		DLog("::R1000InitEventSources: Could not get InterruptEventSource and/or addEventSource.\n");		return false;	}		intSource->enable();		//Registering watchdog (i.e. if timeout exceeds)	timerSource = IOTimerEventSource::timerEventSource(this, 					OSMemberFunctionCast(IOTimerEventSource::Action, this, &RealtekR1000::R1000TxTimeout));						if (!timerSource || loop->addEventSource(timerSource) != kIOReturnSuccess)	{		DLog("::R1000InitEventSources: Could not get timerEventSource and/or addEventSource.\n");		return false;	}		return true;}bool RealtekR1000::R1000OpenAdapter(){	DLog("bool RealtekR1000::R1000OpenAdapter()\n");	R1000HwStart();	return true;}void RealtekR1000::R1000CloseAdapter(){	/* Stop the chip's Tx and Rx processes. */	WriteMMIO8(ChipCmd, 0x00);	/* Disable interrupts by clearing the interrupt mask. */	WriteMMIO16(IntrMask, 0x0000);	/* Update the error counts. */	//TO-DO: FIX-ME, Realy need?	//priv->stats.rx_missed_errors += ReadMMIO32(RxMissed);	WriteMMIO32(RxMissed, 0);}void RealtekR1000::R1000TxClear(){	cur_tx = 0;	dirty_tx = 0;	for(int i = 0; i < NUM_TX_DESC; i++)	{		TxDescArray[i].status = 0;		if (Tx_skbuff[i] != NULL)		{			freePacket(Tx_skbuff[i]);			Tx_skbuff[i] = NULL;		}	}}//Interrupt handlervoid RealtekR1000::R1000Interrupt(OSObject * client, IOInterruptEventSource * src, int count){	// dont process interrupts until we're ready	if(!this->isInitialized)	{		//DLog("Ignoring interrupt, card not initilized yet.\n");		return;	}		// dont process interrupts until we're enabled	if(!this->enabled)	{		//DLog("Ignoring interrupt, card not enabled?\n");		return;	}		//DLog("RealtekR1000::R1000Interrupt(OSObject * client, IOInterruptEventSource * src, int count)\n");		int boguscnt = max_interrupt_work;	unsigned int status = 0;	unsigned int phy_status = 0;		WriteMMIO16(IntrMask, 0x0000);		do 	{		// get status from card		status = ReadMMIO16(IntrStatus);		// from realtek linux driver		// ** hotplug/major error/no more work/shared irq		if (status == 0xFFFF) break;				// from realtek linux driver		// ** write clean mask ? here? unknown, same status		WriteMMIO16(IntrStatus, status);		// if the link status has changed		if(status&LinkChg)			{				DLog("Interrupt :: Link changed?\n");				// read physical status				phy_status = ReadMMIO8(PHYstatus);				// if we have link and physical status				if(phy_status&LinkStatus)				{					// in original R1000 driver? what does this do? never ran except in few conditions and when @ 100mbit					WriteGMII32(0x1f, 0x0001);					WriteGMII32(0x10, 0xf01b);					WriteGMII32(0x1f, 0x0000);					DLog("Interrupt :: Link up?\n");					// report to OSX that link is up					this->setLinkStatus( kIONetworkLinkValid | kIONetworkLinkActive );									}				// link must be down				else				{					// in original R1000 driver? what does this do? never ran except in few conditions and when @ 100mbit					WriteGMII32(0x1f, 0x0001);					WriteGMII32(0x10, 0xf41b);					WriteGMII32(0x1f, 0x0000);					DLog("Interrupt :: Link down?\n");					// report to OSX that link is down					this->setLinkStatus( kIONetworkLinkValid );				}			}				// if no work to be done...exit		if ((status & r1000_intr_mask) == 0) break;		if ((status & TxOK) && (status & TxDescUnavail)) {			// set polling bit			WriteMMIO8(TxPoll, 0x40);			// write status? per realtek linux			WriteMMIO16(IntrStatus, TxDescUnavail);		}				// handle RX		if (status & (RxOK | RxDescUnavail | RxFIFOOver)) {			R1000RxInterrupt();		}				// handle TX		if (status & (TxOK | TxErr)) {			R1000TxInterrupt();		}				boguscnt--;	} 	while (boguscnt > 0);		if (boguscnt <= 0) 	{		//DLog("Too much work at interrupt!\n");		// Clear all interrupt sources		WriteMMIO16(IntrStatus, 0xffff);		}	// write clean mask	WriteMMIO16 ( IntrMask, r1000_intr_mask);}void RealtekR1000::R1000RxInterrupt(){	int lcur_rx;	int pkt_size = 0 ;	int rxdesc_cnt = 0;		struct __mbuf *rx_skb = NULL;	struct	RxDesc	*rxdesc;		lcur_rx = cur_rx;		rxdesc = &RxDescArray[lcur_rx];		while (((OSSwapLittleToHostInt32(rxdesc->status) & OWNbit) == 0) && (rxdesc_cnt < max_interrupt_work))	{		    rxdesc_cnt++;	    if(OSSwapLittleToHostInt32(rxdesc->status) & RxRES)		{			DLog("RX_RING_IS_FULL stalling\n");			//TO-DO: Add error counters			if (OSSwapLittleToHostInt32(rxdesc->status) & (RxRWT|RxRUNT)) ;//priv->stats.rx_length_errors++;			if (OSSwapLittleToHostInt32(rxdesc->status) & RxCRC) ;//priv->stats.rx_crc_errors++;	    }		else		{			pkt_size=static_cast<int>(OSSwapLittleToHostInt32(rxdesc->status) & 0x00001FFF) - 4;						if (pkt_size > rx_pkt_len )			{				DLog("Error -- Rx packet size() > mtu()+14\n");				pkt_size = rx_pkt_len;			}						//rx_skb = Rx_skbuff[lcur_rx];			rx_skb = allocatePacket(MAX_RX_SKBDATA_SIZE);			if (!rx_skb) continue;			bcopy(Rx_dbuff[lcur_rx], mbuf_data(rx_skb), pkt_size);						if (rx_skb != NULL)			{				mbuf_setlen(rx_skb, pkt_size);				//TO-DO: Add network stack notification				//DLog("Receive: packet len %d, mised packets %d\n", pkt_size, ReadMMIO32(RxMissed));				netif->inputPacket(rx_skb, pkt_size, IONetworkInterface::kInputOptionQueuePacket);				netif->flushInputQueue();			}			else			{				DLog("Allocate n_skb failed!\n");			}						// Update rx descriptor			if (lcur_rx == (NUM_RX_DESC - 1))			{				RxDescArray[lcur_rx].status = OSSwapHostToLittleInt32((OWNbit | EORbit) | static_cast<unsigned long>(hw_rx_pkt_len));			}			else			{				RxDescArray[lcur_rx].status = OSSwapHostToLittleInt32(OWNbit | static_cast<unsigned long>(hw_rx_pkt_len));			}		}			    lcur_rx = (lcur_rx +1) % NUM_RX_DESC;	    rxdesc = &RxDescArray[lcur_rx];	}		if (rxdesc_cnt >= max_interrupt_work)	{		DLog(" Too much work at Rx interrupt.\n");	}	cur_rx = lcur_rx;}void RealtekR1000::R1000TxInterrupt(){	unsigned long ldirty_tx, tx_left=0;	int entry = cur_tx % NUM_TX_DESC;    	int txloop_cnt = 0;				ldirty_tx = dirty_tx;	tx_left = cur_tx - ldirty_tx;	//DLog("R1000TxInterrupt cur_tx %d, dirty_tx %d, tx_left %d\n", cur_tx, dirty_tx, tx_left);		while ((tx_left > 0) && (txloop_cnt < max_interrupt_work))	{		if ((OSSwapLittleToHostInt32(TxDescArray[entry].status) & OWNbit) == 0)		{			if (Tx_skbuff[ldirty_tx % NUM_TX_DESC] != NULL)			{				//DLog("Send: R1000TxInterrupt, packet sended to the network, packet size %d, phys addr %x\n", mbuf_len(Tx_skbuff[ldirty_tx % NUM_TX_DESC]), OSSwapLittleToHostInt32(RxDescArray[ldirty_tx % NUM_TX_DESC].buf_addr));				{#ifdef DEBUG					/*uchar *data = Tx_dbuff[ldirty_tx % NUM_TX_DESC];					for(int i = 0; i < mbuf_len(Tx_skbuff[ldirty_tx % NUM_TX_DESC]); i++)						DLog("%02x ", data[i]);										DLog("\n");*/#endif				}				freePacket(Tx_skbuff[ldirty_tx % NUM_TX_DESC]);				Tx_skbuff[ldirty_tx % NUM_TX_DESC] = NULL;			}			else			{				DLog("Tx_skbuff[ldirty_tx % NUM_TX_DESC] is NULL!\n");			}			/*Tx_skbuff_Md[ldirty_tx % NUM_TX_DESC]->complete();			Tx_skbuff_Md[ldirty_tx % NUM_TX_DESC]->release();			Tx_skbuff_Md[ldirty_tx % NUM_TX_DESC] = NULL;*/			ldirty_tx++;			tx_left--;			entry++;		}		txloop_cnt++;	}		if (dirty_tx != ldirty_tx) 	{		dirty_tx = ldirty_tx;		transmitQueue->start();	}}void RealtekR1000::R1000TxTimeout(OSObject *owner, IOTimerEventSource * timer){	DLog("RealtekR1000::R1000TxTimeout(OSObject *owner, IOTimerEventSource * timer)\n");		uchar tmp8;	/* disable Tx, if not already */	tmp8 = ReadMMIO8( ChipCmd );	if (tmp8 & CmdTxEnb)	{		WriteMMIO8 (ChipCmd, tmp8 & ~CmdTxEnb);	}		/* Disable interrupts by clearing the interrupt mask. */	WriteMMIO16(IntrMask, 0x0000);		R1000TxClear();	R1000HwStart();	transmitQueue->start();}/* This is completely open software */

⌨️ 快捷键说明

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