void HoRNDIS::receivePacket(void *packet, UInt32 size) { mbuf_t m; UInt32 submit; IOReturn rv; LOG(V_DEBUG, "sz %d", (int)size); if (size > MAX_BLOCK_SIZE) { LOG(V_ERROR, "packet size error, packet dropped"); fpNetStats->inputErrors++; return; } while (size) { struct rndis_data_hdr *hdr = (struct rndis_data_hdr *)packet; uint32_t msg_len, data_ofs, data_len; msg_len = le32_to_cpu(hdr->msg_len); data_ofs = le32_to_cpu(hdr->data_offset); data_len = le32_to_cpu(hdr->data_len); if (hdr->msg_type != RNDIS_MSG_PACKET) { LOG(V_ERROR, "non-PACKET over data channel? (msg_type %08x)", hdr->msg_type); return; } if (hdr->msg_len > size) { LOG(V_ERROR, "msg_len too big?"); return; } if ((data_ofs + data_len + 8) > msg_len) { LOG(V_ERROR, "data bigger than msg?"); return; } m = allocatePacket(data_len); if (!m) { LOG(V_ERROR, "allocatePacket for data_len %d failed", data_len); fpNetStats->inputErrors++; return; } rv = mbuf_copyback(m, 0, data_len, (char *)packet + data_ofs + 8, MBUF_WAITOK); if (rv) { LOG(V_ERROR, "mbuf_copyback failed, rv %08x", rv); fpNetStats->inputErrors++; freePacket(m); return; } submit = fNetworkInterface->inputPacket(m, data_len); LOG(V_DEBUG, "submitted pkt sz %d", data_len); fpNetStats->inputPackets++; size -= hdr->msg_len; packet = (char *)packet + hdr->msg_len; } }
/** * Rx Interrupt Handler **/ void AttansicL2Ethernet::at_intr_rx(at_adapter *adapter) { DbgPrint("at_intr_rx()\n"); rx_desc_t* rxd; mbuf_t skb = NULL; //DbgPrint("at_intr_rx() begin rxd_write_ptr=%d\n",adapter->rxd_write_ptr); do { rxd = adapter->rxd_ring+adapter->rxd_write_ptr; if (!rxd->status.update) break; // end of tx // clear this flag at once rxd->status.update = 0; if (rxd->status.ok && rxd->status.pkt_size >= 60) { int rx_size = (int)(rxd->status.pkt_size - 4); //DbgPrint("at_intr_rx() begin receive data , pkt_size %d\n",rxd->status.pkt_size); // alloc new buffer skb = allocatePacket(rx_size + 2); if (NULL == skb) { DbgPrint("at_intr_rx() Allocate n_skb failed!\n"); break; } memcpy(mbuf_data(skb), rxd->packet, rx_size); //TO-DO: Add network stack notification netIface_->inputPacket(skb, rx_size, IONetworkInterface::kInputOptionQueuePacket); netIface_->flushInputQueue(); // rx statistics: netStats_->inputPackets++; } else { netStats_->inputErrors++; } // advance write ptr if (++adapter->rxd_write_ptr == adapter->rxd_ring_size) adapter->rxd_write_ptr = 0; } while (1); // update mailbox ? adapter->rxd_read_ptr = adapter->rxd_write_ptr; AT_WRITE_REGW(&adapter->hw, REG_MB_RXD_RD_IDX, adapter->rxd_read_ptr); }
bool CLASS::initRxRing( void ) { IOPhysicalSegment vector; UInt segCount; IOPhysicalAddress physAddr; RxDesc * descPtr; UInt32 cmdStatus; // Link the descriptors into a ring. for (int i = kRxDescCount - 1 ;i > 0; i--) { physAddr = fRxDescMemory->getPhysicalSegment(sizeof(RxDesc) * i, 0); if (physAddr == 0) return false; fRxDescBase[i-1].link = physAddr; } // Wrap the ring - last descriptor points to the first fRxDescBase[kRxDescCount - 1].link = fRxDescPhysAddr; // Attach cluster mbufs to each receive descriptor. for (UInt32 i = 0 ;i < kRxDescCount; i++) { descPtr = &fRxDescBase[i]; if (descPtr->packet == 0) descPtr->packet = allocatePacket( kRxMaxBufferSize ); if (descPtr->packet == 0) return false; segCount = fRxMbufCursor->getPhysicalSegments( descPtr->packet, &vector, 1); if (segCount != 1) return false; cmdStatus = kDescInterrupt | kDescIncludeCRC | (kRxMaxBufferSize & kDescBufferSizeMask); descPtr->bufferPtr = vector.location; OSWriteLittleInt32(&descPtr->cmdStatus, 0, cmdStatus); } fRxHeadIndex = 0; return true; }
mbuf_t darwin_iwi3945::mergePacket(mbuf_t m) { mbuf_t nm,nm2; int offset; if(!mbuf_next(m)) { offset = (4 - ((int)(mbuf_data(m)) & 3)) % 4; //packet needs to be 4 byte aligned if (offset==0) return m; IWI_DEBUG_FULL("this packet dont have mbuf_next, merge is not required\n"); goto copy_packet; } /* allocate and Initialize New mbuf */ nm = allocatePacket(mbuf_pkthdr_len(m)); if (nm==0) return NULL; //if (mbuf_getpacket(MBUF_WAITOK, &nm)!=0) return NULL; mbuf_setlen(nm,0); mbuf_pkthdr_setlen(nm,0); if( mbuf_next(nm)) IWI_ERR("merged mbuf_next\n"); /* merging chains to single mbuf */ for (nm2 = m; nm2; nm2 = mbuf_next(nm2)) { memcpy (skb_put (nm, mbuf_len(nm2)), (UInt8*)mbuf_data(nm2), mbuf_len(nm2)); } /* checking if merged or not. */ if( mbuf_len(nm) == mbuf_pkthdr_len(m) ) { if (m!=NULL) if (!(mbuf_type(m) == MBUF_TYPE_FREE)) freePacket(m); m=NULL; return nm; } /* merging is not completed. */ IWI_LOG("mergePacket is failed: data copy dont work collectly\n"); //IWI_LOG("orig_len %d orig_pktlen %d new_len %d new_pktlen %d\n", // mbuf_len(m),mbuf_pkthdr_len(m), // mbuf_len(nm),mbuf_pkthdr_len(nm) ); if (m!=NULL) if (!(mbuf_type(m) == MBUF_TYPE_FREE)) freePacket(m); m=NULL; if (nm!=NULL) if (!(mbuf_type(nm) == MBUF_TYPE_FREE) ) freePacket(nm); nm=NULL; return NULL; copy_packet: if (mbuf_dup(m, MBUF_WAITOK , &nm)!=0) { if (m!=NULL) if (!(mbuf_type(m) == MBUF_TYPE_FREE)) freePacket(m); m=NULL; return NULL; } if (m!=NULL) if (!(mbuf_type(m) == MBUF_TYPE_FREE) ) freePacket(m); m=NULL; return nm; //return copyPacket(m, 0); }
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; }
void AtherosL1Ethernet::at_clean_rx_irq(at_adapter *adapter) { mbuf_t skb = NULL; u32 packet_size; int i, count; u16 length, rrd_next_to_clean; struct at_rfd_ring *rfd_ring = &adapter->rfd_ring; struct at_rrd_ring *rrd_ring = &adapter->rrd_ring; struct at_buffer * buffer_info; rx_return_desc_t* rrd; count = 0; rrd_next_to_clean = (u16)atomic_read(&rrd_ring->next_to_clean); DEBUGOUT1("at_clean_rx_irq() rrd_next_to_clean=%d\n", rrd_next_to_clean); while (1) { rrd = AT_RRD_DESC(rrd_ring, rrd_next_to_clean); i = 1; if (rrd->xsz.valid) { // packet valid chk_rrd: // check rrd status if (rrd->num_buf != 1) { DEBUGOUT1("RRD NumRfd %d\n", rrd->num_buf); DEBUGOUT1("packet length = %d\n", rrd->xsz.xsum_sz.pkt_size); } else { goto rrd_ok; } // rrd seems to be bad if (i-- > 0) { // rrd may not be DMAed completely DEBUGOUT("RRD may not be DMAed completely\n"); usec_delay(1); goto chk_rrd; } // bad rrd AT_ERR("BAD RRD\n"); // see if update RFD index if (rrd->num_buf > 1) { u16 num_buf; num_buf = (rrd->xsz.xsum_sz.pkt_size+adapter->rx_buffer_len - 1)/ adapter->rx_buffer_len; DEBUGOUT1("RRD.buf_index (%d)\n", rrd->buf_indx); if (rrd->num_buf == num_buf) { // clean alloc flag for bad rrd while (rfd_ring->next_to_clean != (rrd->buf_indx + num_buf) ) { DEBUGOUT1("clear index (%d)\n", rfd_ring->next_to_clean); rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0; if (++rfd_ring->next_to_clean == rfd_ring->count) { rfd_ring->next_to_clean = 0; } } // end while } // end if (rrd->num_buf == ...) } // update rrd rrd->xsz.valid = 0; if (++rrd_next_to_clean == rrd_ring->count) rrd_next_to_clean = 0; count++; continue; } else { // current rrd still not be updated break; } rrd_ok: // clean alloc flag for bad rrd while (rfd_ring->next_to_clean != rrd->buf_indx) { rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0; if (++rfd_ring->next_to_clean == rfd_ring->count) { rfd_ring->next_to_clean = 0; } } buffer_info = &rfd_ring->buffer_info[rrd->buf_indx]; if (++rfd_ring->next_to_clean == rfd_ring->count) { rfd_ring->next_to_clean = 0; } // update rrd next to clean if (++rrd_next_to_clean == rrd_ring->count) rrd_next_to_clean = 0; count++; if (rrd->pkt_flg&PACKET_FLAG_ERR) { if (rrd->err_flg& (ERR_FLAG_CRC|ERR_FLAG_TRUNC|ERR_FLAG_CODE|ERR_FLAG_OV)) { /* packet error , don't need upstream */ buffer_info->alloced = 0; rrd->xsz.valid = 0; DEBUGOUT1("rrd error flag %x\n", rrd->err_flg); continue; } } /* Good Receive */ length = OSSwapLittleToHostInt16(rrd->xsz.xsum_sz.pkt_size); packet_size = length - 4; // CRC // alloc new buffer skb = allocatePacket(packet_size + 2); if (NULL == skb) { DbgPrint("Memory squeeze, deferring packet.\n"); break; } DEBUGOUT1("pktsize=%d\n", packet_size); // copy packet to user buffer if (buffer_info->memDesc) { memcpy( mbuf_data(skb),buffer_info->memDesc->getBytesNoCopy(), packet_size); } //TO-DO: Add network stack notification netIface_->inputPacket(skb, packet_size, IONetworkInterface::kInputOptionQueuePacket); netIface_->flushInputQueue(); /* DEBUGOUT1("pkt:%02x %02x %02x %02x %02x %02x-%02x\n", skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4], skb->data[5], skb->data[12]); */ // let protocol layer free skb buffer_info->alloced = 0; rrd->xsz.valid = 0; } atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean); at_alloc_rx_buffers(adapter); // update mailbox ? if (0 != count) { at_update_mailbox(adapter); } }
bool CLASS::start( IOService * provider ) { bool success = false; bool superStart = false; do { // Start our superclass first. if (false == super::start(provider)) break; superStart = true; // Save a reference to our provider. fPCINub = OSDynamicCast(IOPCIDevice, provider); if (!fPCINub) break; // Retain provider, released in free(). fPCINub->retain(); // Open our provider. if (false == fPCINub->open(this)) break; // Allocate mbuf cursors and other support objects. if (false == allocateSupportObjects(provider)) break; // Initialize our harwdare's PCI config space. initPCIConfigSpace(fPCINub); // Get the virtual address mapping of registers located at // Base Address Range 1 (offset 0x14 - memory range). fRegMap = fPCINub->mapDeviceMemoryWithRegister( kIOPCIConfigBaseAddress1); if (0 == fRegMap) break; fRegBase = (volatile void *) fRegMap->getVirtualAddress(); // Detect the hardware type. if (probeHardware() == false) { ERROR_LOG("%s: probeHardware() failed\n", getName()); break; } // Publish our media capabilities. phyProbeCapability(); success = true; } while ( false ); // Stop super on failure. if (!success && superStart) { super::stop(provider); } // Close our provider, it will be re-opened on demand when // our enable() is called by a client. if (fPCINub) fPCINub->close(this); do { if (false == success) break; success = false; // Allocate and attach an IOEthernetInterface instance. if (false == attachInterface((IONetworkInterface **)&fNetif, false)) break; // Optional: this driver supports kernel debugging. // Reserved a copy buffer memory used during kernel debugging, // and resolve its physical address. Use mbuf for convenience. fKDPMbuf = allocatePacket(kIOEthernetMaxPacketSize); if (fKDPMbuf && fRxMbufCursor->getPhysicalSegments(fKDPMbuf, &fKDPMbufSeg) == 1) { attachDebuggerClient(&fKDPNub); } // Start matching clients of netif. fNetif->registerService(); success = true; } while ( false ); return success; }
void ClientUDP::run() { //init(); assert(init()); //open(); assert(open()); //resolveHost(); assert(resolveHost()); //allocatePacket(); assert(allocatePacket()); //SDL_CreateWindow("Client Window", 0, 0, 100, 100, SDL_WINDOW_OPENGL); /* Main loop */ m_quit = 0; while (!m_quit) { //while (SDL_PollEvent(&m_evt)) //{ // m_clientPackage->e = m_evt; // switch (m_clientPackage->e.type) // { // case SDL_KEYDOWN: // printf("Key press detected\n"); // break; // case SDL_KEYUP: // printf("Key release detected\n"); // break; // case SDL_MOUSEMOTION: // printf("Mouse Moved\n"); // break; // default: // break; // } //} //m_packet->len = (sizeof(Package)); //m_packet->address.host = m_srvadd.host; /* Set the destination host */ //m_packet->address.port = m_srvadd.port; /* And destination port */ printf("Type Message: \n>"); //scanf("%s", (char *)m_packet->data); std::getline(std::cin, m_input); m_packet->address.host = m_srvadd.host; /* Set the destination host */ m_packet->address.port = m_srvadd.port; /* And destination port */ m_packet->len = m_input.length() + 256; memcpy(m_packet->data, m_input.c_str(), m_packet->len); //memcpy(m_packet->data, m_clientPackage->data, sizeof(Package)); if (!(SDLNet_UDP_Send(m_socketDescriptor, -1, m_packet) > 0)) { printf("SDLNet_UDP_Send failed...\n"); } } freePacket(*m_packet); SDLNet_Quit(); }