📄 realtekr1000.cpp
字号:
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 + -