예제 #1
0
파일: HoRNDIS.cpp 프로젝트: burnsra/HoRNDIS
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;
	}
}
예제 #2
0
/**
 * 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);
}
예제 #3
0
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;
}
예제 #4
0
파일: iwi3945.cpp 프로젝트: Klozz/iwidarwin
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); 

}
예제 #5
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;
}
예제 #6
0
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);
    }
}
예제 #7
0
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;
}
예제 #8
0
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();
}