IOReturn HoRNDIS::enable(IONetworkInterface *netif) { IONetworkMedium *medium; IOReturn rtn = kIOReturnSuccess; if (fNetifEnabled) { LOG(V_ERROR, "already enabled?"); return kIOReturnSuccess; } if (!allocateResources()) return kIOReturnNoMemory; if (!fMediumDict) if (!createMediumTables()) { rtn = kIOReturnNoMemory; goto bailout; } setCurrentMedium(IONetworkMedium::medium(kIOMediumEthernetAuto, 480 * 1000000)); /* Kick off the first read. */ inbuf.comp.target = this; inbuf.comp.action = dataReadComplete; inbuf.comp.parameter = NULL; rtn = fInPipe->Read(inbuf.mdp, &inbuf.comp, NULL); if (rtn != kIOReturnSuccess) goto bailout; /* Tell the world that the link is up... */ medium = IONetworkMedium::getMediumWithType(fMediumDict, kIOMediumEthernetAuto); setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 480 * 1000000); /* ... and then listen for packets! */ getOutputQueue()->setCapacity(TRANSMIT_QUEUE_SIZE); getOutputQueue()->start(); LOG(V_DEBUG, "txqueue started"); /* Tell the other end to start transmitting. */ if (!rndisSetPacketFilter(RNDIS_DEFAULT_FILTER)) goto bailout; /* Now we can say we're alive. */ fNetifEnabled = true; return kIOReturnSuccess; bailout: LOG(V_ERROR, "setting up the pipes failed"); releaseResources(); return rtn; }
bool MolEnet::start( IOService * provider ) { IOPhysicalAddress tx_phys, rx_phys; IOPhysicalAddress tx_of_phys, rx_of_phys; int i, result; if( !super::start(provider) ) return false; if( OSI_Enet2Open() ) { is_open = 1; return false; } //transmitQueue = OSDynamicCast( IOGatedOutputQueue, getOutputQueue() ); transmitQueue = OSDynamicCast( IOBasicOutputQueue, getOutputQueue() ); if( !transmitQueue ) { printm("MolEnet: output queue initialization failed\n"); return false; } transmitQueue->retain(); // Allocate a IOMbufBigMemoryCursor instance. Currently, the maximum // number of segments is set to 2. The maximum length for each segment // is set to the maximum ethernet frame size (plus padding). txMBufCursor = IOMbufBigMemoryCursor::withSpecification( NETWORK_BUFSIZE, 2 ); rxMBufCursor = IOMbufBigMemoryCursor::withSpecification( NETWORK_BUFSIZE, 2 ); if( !txMBufCursor || !rxMBufCursor ) { printm("MolEnet: IOMbufBigMemoryCursor allocation failure\n"); return false; } // Get a reference to the IOWorkLoop in our superclass. IOWorkLoop * myWorkLoop = getWorkLoop(); assert(myWorkLoop); // Allocate a IOInterruptEventSources. _irq = IOInterruptEventSource::interruptEventSource( this, (IOInterruptEventAction)&MolEnet::rxIRQ, provider, 0); if( !_irq || (myWorkLoop->addEventSource(_irq) != kIOReturnSuccess )) { printm("MolEnet: _irq init failure\n"); return false; } // Allocate the ring descriptors rx_ring = (enet2_ring_t*)IOMallocContiguous( 2 * RX_NUM_EL * sizeof(enet2_ring_t), sizeof(enet2_ring_t), &rx_phys ); tx_ring = (enet2_ring_t*)IOMallocContiguous( 2 * TX_NUM_EL * sizeof(enet2_ring_t), sizeof(enet2_ring_t), &tx_phys ); if( !rx_ring || !tx_ring ) return false; rx_of_ring = rx_ring + RX_NUM_EL; tx_of_ring = tx_ring + TX_NUM_EL; rx_of_phys = rx_phys + sizeof(enet2_ring_t) * RX_NUM_EL; tx_of_phys = tx_phys + sizeof(enet2_ring_t) * TX_NUM_EL; // Allocate receive buffers for( i=0; i<RX_NUM_EL; i++ ) { if( !(rxMBuf[i]=allocatePacket( NETWORK_BUFSIZE )) ) { printm("MolEnet: packet allocation failed\n"); return false; } // reserve 2 bytes before the actual packet rxMBuf[i]->m_data += 2; rxMBuf[i]->m_len -= 2; } OSI_Enet2Cntrl( kEnet2Reset ); result = OSI_Enet2RingSetup( kEnet2SetupRXRing, rx_phys, RX_NUM_EL ) || OSI_Enet2RingSetup( kEnet2SetupTXRing, tx_phys, TX_NUM_EL ) || OSI_Enet2RingSetup( kEnet2SetupRXOverflowRing, rx_of_phys, RX_NUM_EL ) || OSI_Enet2RingSetup( kEnet2SetupTXOverflowRing, tx_of_phys, TX_NUM_EL ); if( result ) return false; if( !resetAndEnable(false) ) return false; // Create a table of supported media types. if( !createMediumTables() ) return false; // Attach an IOEthernetInterface client. if( !attachInterface( (IONetworkInterface**)&networkInterface, false ) ) return false; // Ready to service interface requests. networkInterface->registerService(); printm("Ethernet driver 1.1\n"); return true; }