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

📄 realtekr1000.cpp

📁 Mac OS X 下的网卡驱动
💻 CPP
📖 第 1 页 / 共 4 页
字号:
			break;		case MEDIUM_INDEX_1000HD:			R1000SetMedium(SPEED_1000, DUPLEX_HALF, AUTONEG_DISABLE);			break;		case MEDIUM_INDEX_1000FD:			R1000SetMedium(SPEED_1000, DUPLEX_FULL, AUTONEG_DISABLE);			break;		}		setCurrentMedium(medium);	}	else	{		DLog("Selected medium is NULL\n");	}		if (ReadMMIO8(PHYstatus) & LinkStatus)	{		if (ReadMMIO8(PHYstatus) & _1000Mbps) setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, getSelectedMedium(), 1000 * MBit, NULL);		else if(ReadMMIO8(PHYstatus) & _100Mbps) setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, getSelectedMedium(), 100 * MBit, NULL);		else if(ReadMMIO8(PHYstatus) & _10Mbps) setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, getSelectedMedium(), 10 * MBit, NULL);	}	else	{			setLinkStatus(kIONetworkLinkValid, NULL, 0, NULL);	}	return kIOReturnSuccess;}/* * Configures a newly created network interface object. * This method configures an interface object that was created by createInterface().  * Subclasses can override this method to customize and examine the interface object that will be  * attached to the controller as a client.*/bool RealtekR1000::configureInterface(IONetworkInterface *netif){	DLog("RealtekR1000::configureInterface(IONetworkInterface *interface)\n");	IONetworkData * data;    if (!BaseClass::configureInterface(netif)) return false;	    // Get the generic network statistics structure.    data = netif->getParameter( kIONetworkStatsKey );    if ( !data || !(netStats = (IONetworkStats *) data->getBuffer()) )     {        return false;    }    // Get the Ethernet statistics structure.    data = netif->getParameter( kIOEthernetStatsKey );    if ( !data || !(etherStats = (IOEthernetStats *) data->getBuffer()) )     {        return false;    }    return true;}/* * Method called by IONetworkController prior to the initial getWorkLoop() call.*/bool RealtekR1000::createWorkLoop(){	DLog("RealtekR1000::createWorkLoop()\n");	workLoop = IOWorkLoop::workLoop();	if (workLoop) return true;	else return false;}IOWorkLoop *RealtekR1000::getWorkLoop() const{	DLog("RealtekR1000::getWorkLoop()\n");	return workLoop;}/* * Gets the Ethernet controller's permanent station address. * Ethernet drivers must implement this method, by reading the address from hardware and writing  * it to the buffer provided. This method is called from the workloop context.*/IOReturn RealtekR1000::getHardwareAddress(IOEthernetAddress *addr){	DLog("RealtekR1000::getHardwareAddress(IOEthernetAddress *addr)\n");	uchar bytes[MAC_ADDR_LEN];		for (uchar i = 0; i < MAC_ADDR_LEN ; i++)	{		bytes[i] = ReadMMIO8(MAC0 + i);	}		addr->bytes[0] = bytes[0];    addr->bytes[1] = bytes[1];    addr->bytes[2] = bytes[2];    addr->bytes[3] = bytes[3];    addr->bytes[4] = bytes[4];    addr->bytes[5] = bytes[5];	return kIOReturnSuccess;}/* * Enables or disables promiscuous mode. * Called by enablePacketFilter() or disablePacketFilter() when there is a change  * in the activation state of the promiscuous filter identified by kIOPacketFilterPromiscuous.  * This method is called from the workloop context.*/IOReturn RealtekR1000::setPromiscuousMode(bool enabled){	DLog("RealtekR1000::setPromiscuousMode(bool enabled)\n");		ulong rx_mode;	ulong mc_filter[2];		if (enabled)	{		//Accept all multicasts		mc_filter[0] = mc_filter[1] = 0xffffffff;				rx_mode = r1000_rx_config | AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys |					(ReadMMIO32(RxConfig) & rtl_chip_info[chipset].RxConfigMask);	}	else	{		//Restoring old multicast filter		mc_filter[0] = mc_filter0;		mc_filter[1] = mc_filter1;				rx_mode = r1000_rx_config | 					AcceptBroadcast | AcceptMulticast | AcceptMyPhys | 					(ReadMMIO32(RxConfig) & rtl_chip_info[chipset].RxConfigMask);	}		WriteMMIO32(RxConfig, rx_mode);	if ((mcfg == MCFG_METHOD_11) || (mcfg == MCFG_METHOD_12) ||	    (mcfg == MCFG_METHOD_13) || (mcfg == MCFG_METHOD_14) ||	    (mcfg == MCFG_METHOD_15)) 	{		WriteMMIO32(MAR0 + 0, 0xffffffff);		WriteMMIO32(MAR0 + 4, 0xffffffff);	}	else	{		WriteMMIO32(MAR0 + 0, mc_filter[0]);		WriteMMIO32(MAR0 + 4, mc_filter[1]);	}		return kIOReturnSuccess;}/* * Enables or disables multicast mode. * Called by enablePacketFilter() or disablePacketFilter() when there is a  * change in the activation state of the multicast filter identified by kIOPacketFilterMulticast.  * This method is called from the workloop context.*/IOReturn RealtekR1000::setMulticastMode(bool enabled){	DLog("RealtekR1000::setMulticastMode(bool enabled)\n");			ulong rx_mode;	if (enabled)	{		rx_mode = r1000_rx_config | 					AcceptBroadcast | AcceptMulticast | AcceptMyPhys | 					(ReadMMIO32(RxConfig) & rtl_chip_info[chipset].RxConfigMask);	}	else	{		rx_mode = (r1000_rx_config | (ReadMMIO32(RxConfig) & rtl_chip_info[chipset].RxConfigMask)) &					~AcceptMulticast;		}	WriteMMIO32(RxConfig, rx_mode);	return kIOReturnSuccess;}/* Sets the list of multicast addresses a multicast filter should use to match  * against the destination address of an incoming frame. * This method sets the list of multicast addresses that the multicast filter should use  * to match against the destination address of an incoming frame. The frame should be  * accepted when a match occurs. Called when the multicast group membership of an interface object is changed.  * Drivers that support kIOPacketFilterMulticast should override this method and update the  * hardware multicast filter using the list of Ethernet addresses provided. Perfect multicast filtering  * is preferred if supported by the hardware, in order to reduce the number of unwanted packets received.  * If the number of multicast addresses in the list exceeds what the hardware is capable of supporting,  * or if perfect filtering is not supported, then ideally the hardware should be programmed to perform  * imperfect filtering, through some form of hash filtering mechanism. Only as a last resort should the driver  * enable reception of all multicast packets to satisfy this request. This method is called from the workloop  * context, and only if the driver reports kIOPacketFilterMulticast support in getPacketFilters().*/IOReturn RealtekR1000::setMulticastList(IOEthernetAddress *addrs, UInt32 count){	DLog("RealtekR1000::setMulticastList(IOEthernetAddress *addrs, UInt32 count)\n");	//DLog("Forcing method!\n");	//return kIOReturnSuccess;	//It seems, that RTL8168 family uses the same filter hashing method, as VIA Rhine,	//so this part of code taken from ViaRhine Mac OS X driver by Yang Wu/*	#ifdef DEBUG	for (int i = 0; i < kIOEthernetAddressSize; ++i )	{		DLog("%x:", addrs->bytes[i]);	}	DLog(", count = %d. \n", count );#endif*/	ulong mc_filter[2];		if (count > multicast_filter_limit)	{		DLog("Break multicast filter limit, accept all!");		mc_filter[0] = mc_filter[1] = 0xffffffff;	}	else 	{		for ( UInt32 i = 0; i < count; i++, addrs++ )		{			int bit = 0;			bit = ether_crc(6, reinterpret_cast<uchar *>(addrs)) >> 26;			DLog("Multicast bits after crc calc: 0x%8.8x.\n", bit);			if (bit < 32) mc_filter[0] |= (1 << bit);			else mc_filter[1] |= (1 << (bit - 32));		}	}	if ((mcfg == MCFG_METHOD_11) || (mcfg == MCFG_METHOD_12) ||	    (mcfg == MCFG_METHOD_13) || (mcfg == MCFG_METHOD_14) ||	    (mcfg == MCFG_METHOD_15)) 	{		WriteMMIO32(MAR0 + 0, 0xffffffff);		WriteMMIO32(MAR0 + 4, 0xffffffff);	}	else	{		WriteMMIO32(MAR0 + 0, mc_filter[0]);		WriteMMIO32(MAR0 + 4, mc_filter[1]);	}		return kIOReturnSuccess;}/* * Debugger polled-mode transmit handler. * This method must be implemented by a driver that supports kernel debugging. * pkt - pointer to a transmit buffer containing the packet to be sent on the network. * pktSize - the size of the transmit buffer in bytes.*/void RealtekR1000::sendPacket(void * pkt, UInt32 pkt_len){	DLog("RealtekR1000::sendPacket(void * pkt, UInt32 pkt_len)\n");}/* * Debugger polled-mode receive handler. * This method must be implemented by a driver that supports kernel debugging. * pkt - address of a receive buffer where the received packet should be stored. This buffer has room for 1518 bytes. * pktSize - address where the number of bytes received must be recorded. Set this to zero if no packets were received during the timeout interval. * timeout - the maximum amount of time in milliseconds to poll for a packet to arrive before this method must return.*/void RealtekR1000::receivePacket(void *pkt, UInt32 *pkt_len, UInt32 timeout){	DLog("RealtekR1000::receivePacket(void *pkt, UInt32 *pkt_len, UInt32 timeout)\n");}/* * Implements the framework for a generic network controller.*/IOReturn RealtekR1000::registerWithPolicyMaker(IOService *policyMaker){	DLog("RealtekR1000::registerWithPolicyMaker(IOService *policyMaker)\n");		//Grabed from ViaRhine    enum 	{        kPowerStateOff = 0,        kPowerStateOn,        kPowerStateCount    };    static IOPMPowerState powerStateArray[ kPowerStateCount ] =    {        { 1,0,0,0,0,0,0,0,0,0,0,0 },        { 1,IOPMDeviceUsable,IOPMPowerOn,IOPMPowerOn,0,0,0,0,0,0,0,0 }    };    IOReturn ret;    ret = policyMaker->registerPowerDriver( this, powerStateArray,                                            kPowerStateCount );        return ret;}IOReturn RealtekR1000::setPowerState(unsigned long powerStateOrdinal, IOService *policyMaker){	DLog("Realtek R1000::setPowerState(unsigned long powerStateOrdinal, IOService *policyMaker)\n");    if ( 0 == powerStateOrdinal ) 	{     // Going to sleep. Perform state-saving tasks here.	 DLog("going to sleep...\n");	 // power down nic	 //WriteGMII32(0x1F, 0x0000);	 //WriteGMII32(0x0E, 0x0200);	 // report to OSX that link is down	 this->setLinkStatus( kIONetworkLinkValid );	}	else	{     // Waking up. Perform device initialization here.	 DLog("waking/wake up from sleep...\n");	 // power up nic 	 //WriteGMII32(0x1F, 0x0000);	 //WriteGMII32(0x0E, 0x0000);     // report to OSX that link is up     this->setLinkStatus( kIONetworkLinkValid | kIONetworkLinkActive );    }	//TO-DO: Add power state support (IOPMAckImplied)	return IOPMAckImplied;}/*IOReturn RealtekR1000::getMaxPacketSize(UInt32 *maxSize) const{	return kIOReturnUnsupported;	*maxSize = MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN + FCS_LEN;		return kIOReturnSuccess;}*//*IOReturn RealtekR1000::setMaxPacketSize(UInt32 maxSize){	DLog("RealtekR1000::setMaxPacketSize(UInt32 maxSize) Packet size %d", maxSize);		maxSize = maxSize - ETH_HDR_LEN - FCS_LEN;	if (maxSize > MAX_JUMBO_FRAME_MTU)	{		DLog("New MTU is too high!\n");		return kIOReturnUnsupported;	}		curr_mtu_size = maxSize;	tx_pkt_len = maxSize + ETH_HDR_LEN;	rx_pkt_len = maxSize + ETH_HDR_LEN;	hw_rx_pkt_len = rx_pkt_len + 8;		WriteMMIO8 ( Cfg9346, Cfg9346_Unlock);	WriteMMIO16	(RxMaxSize, static_cast<unsigned short>(hw_rx_pkt_len));	WriteMMIO8 ( Cfg9346, Cfg9346_Lock);		R1000CloseAdapter();	R1000OpenAdapter();		return kIOReturnSuccess;}*//* *  Private methods *///=================================================================//	PHYAR//	bit		Symbol//	31		Flag//	30-21	reserved//	20-16	5-bit GMII/MII register address//	15-0	16-bit GMII/MII register data//=================================================================void RealtekR1000::WriteGMII32(int RegAddr, int value ){	int	i;	WriteMMIO32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);	//udelay(1000); //Microseconds ?	IODelay(1000);	for( i = 2000; i > 0 ; i--)	{		// Check if the RTL8169 has completed writing to the specified MII register		if (!(ReadMMIO32(PHYAR) & 0x80000000))		{			break;		}		else		{			//udelay(100);			IODelay(100);		}// end of if( ! (RTL_R32(PHYAR)&0x80000000) )	}// end of for() loop}int RealtekR1000::ReadGMII32(int RegAddr){	int i, value = -1;	WriteMMIO32( PHYAR, 0x0 | (RegAddr&0xFF)<<16);	//udelay(1000);	IODelay(1000);	for( i = 2000; i > 0 ; i--){		// Check if the RTL8169 has completed retrieving data from the specified MII register		if( ReadMMIO32(PHYAR) & 0x80000000 )		{			value = static_cast<int>((ReadMMIO32(PHYAR) & 0xFFFF));			break;		}		else		{			//udelay(100);			IODelay(100);		}// end of if( RTL_R32(PHYAR) & 0x80000000 )	}// end of for() loop	return value;}bool RealtekR1000::R1000InitBoard(){	pciDev->setBusMasterEnable(true);	pciDev->setIOEnable(true);	pciDev->setMemoryEnable(true);			vendorId = pciDev->configRead16(0);	deviceId = pciDev->configRead16(2);	pciDev->enablePCIPowerManagement();		IOSleep(10);		pioBase = pciDev->configRead16(kIOPCIConfigBaseAddress0) & 0xFFFC;	DLog("mmio/pio base 0x%04x\n", pioBase);	mmioBase = pciDev->mapDeviceMemoryWithRegister(kIOPCIConfigBaseAddress0);		if (!mmioBase) 	{		DLog("Couldn't setup memory io\n");		DLog("Forcing to port IO\n");		pciDev->setMemoryEnable(false);		pciDev->setIOEnable(true);		forcedPio = true;	}	else DLog("Memory mapped at virt addr 0x%x, phys addr 0x%x\n", mmioBase->getVirtualAddress(),						mmioBase->getPhysicalAddress());														// Soft reset the chip.	WriteMMIO8 ( ChipCmd, CmdReset);	// Check that the chip has finished the reset.	for (int i = 1000; i > 0; i--)	{		if ((ReadMMIO8(ChipCmd) & CmdReset) == 0)		{			break;		}		else		{			IODelay(10);		}	}		// identify config method	{		unsigned long val32 = (ReadMMIO32(TxConfig) & 0x7c800000);		if (val32 == 0x38800000) mcfg = MCFG_METHOD_15;		else if (val32 == 0x30800000) mcfg = MCFG_METHOD_14;		else if (val32 == 0x34000000) mcfg = MCFG_METHOD_13;		else if (val32 == 0x38000000) mcfg = MCFG_METHOD_12;		else if (val32 == 0x30000000) mcfg = MCFG_METHOD_11;		else if (val32 == 0x18000000) mcfg = MCFG_METHOD_5;		else if (val32 == 0x10000000) mcfg = MCFG_METHOD_4;		else if (val32 == 0x04000000) mcfg = MCFG_METHOD_3;		else if (val32 == 0x00800000) mcfg = MCFG_METHOD_2;		else if (val32 == 0x00000000) mcfg = MCFG_METHOD_1;		else mcfg = MCFG_METHOD_1;	}	{		uchar val8 = static_cast<uchar>(ReadGMII32(3)&0x000f);		if (val8 == 0x00)		{			pcfg = PCFG_METHOD_1;		}		else if (val8 == 0x01)		{			pcfg = PCFG_METHOD_2;		}		else if (val8 == 0x02) 		{			pcfg = PCFG_METHOD_3;		}		else		{			pcfg = PCFG_METHOD_3;		}	}	DLog("mcfg %d, pcfg %d\n", mcfg, pcfg);		for(int i = sizeof(rtl_chip_info)/sizeof(RtlChipInfo) - 1; i >= 0; --i)		if (rtl_chip_info[i].mcfg == mcfg) chipset = i;			DLog("Chip %s detected\n", rtl_chip_info[chipset].name);	return true;

⌨️ 快捷键说明

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