Ejemplo n.º 1
0
VOID NTAPI
ProSendPackets(
    IN  NDIS_HANDLE     NdisBindingHandle,
    IN  PPNDIS_PACKET   PacketArray,
    IN  UINT            NumberOfPackets)
{
    PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
    PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
    KIRQL RaiseOldIrql;
    NDIS_STATUS NdisStatus;
    UINT i;

    if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
    {
       if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
       {
          (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
           Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets);
       }
       else
       {
          /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
          KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
          (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
           Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets);
          KeLowerIrql(RaiseOldIrql);
          for (i = 0; i < NumberOfPackets; i++)
          {
             NdisStatus = NDIS_GET_PACKET_STATUS(PacketArray[i]);
             if (NdisStatus != NDIS_STATUS_PENDING)
                 MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
          }
       }
     }
     else
     {
       if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
       {
          for (i = 0; i < NumberOfPackets; i++)
          {
             NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
                           Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags);
             if (NdisStatus != NDIS_STATUS_PENDING)
                 MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
          }
       }
       else
       {
         /* Send is called at DISPATCH_LEVEL for all serialized miniports */
         KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
         for (i = 0; i < NumberOfPackets; i++)
         {
            NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
                           Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags);
            if (NdisStatus != NDIS_STATUS_PENDING)
                MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
         }
         KeLowerIrql(RaiseOldIrql);
       }
     }
}
Ejemplo n.º 2
0
/*
 *************************************************************************
 *  DeliverFullBuffers
 *************************************************************************
 *
 *  Deliver received packets to the protocol.
 *
 */
VOID DeliverFullBuffers(IrDevice *thisDev)
{
	int rcvBufIndex = thisDev->firstRcvBufIndex;

	DBGOUT(("==> DeliverFullBuffers"));



	/*
	 *  Deliver all full rcv buffers
	 */
	while (rcvBufIndex != NO_BUF_INDEX){
		rcvBuffer *rcvBuf = &thisDev->rcvBufs[rcvBufIndex];
		NDIS_STATUS stat;
		PNDIS_BUFFER packetBuf;
		SLOW_IR_FCS_TYPE fcs;

		switch (rcvBuf->state){

			case STATE_FREE:
			case STATE_PENDING:
				/*
				 *  This frame was already delivered.  Just go to the next one.
				 */
				break;
		
			case STATE_FULL:

				/*
				 *  The packet we have already has had BOFs, EOF, and
				 *  escape-sequences removed.  
				 *  It contains an FCS code at the end,
				 *  which we need to verify and then remove before
				 *  delivering the frame.
				 *  We compute the FCS on the packet with the packet FCS
				 *  attached; this should produce the constant value GOOD_FCS.
				 */
				fcs = ComputeFCS(rcvBuf->dataBuf, rcvBuf->dataLen);

				if (fcs != GOOD_FCS){
					/*
					 *  FCS Error.  Drop this frame.
					 */
					DBGERR(("Bad FCS in DeliverFullBuffers 0x%x!=0x%x.", (UINT)fcs, (UINT)GOOD_FCS));
					rcvBuf->state = STATE_FREE;

					DBGSTAT(("Dropped %d/%d packets; packet with BAD FCS (%xh!=%xh):", 
							++thisDev->packetsDropped, thisDev->packetsDropped + thisDev->packetsRcvd, fcs, GOOD_FCS));
					DBGPRINTBUF(rcvBuf->dataBuf, rcvBuf->dataLen);
					break;
				}


				/*
				 *  Remove the FCS from the end of the packet.
				 */
				rcvBuf->dataLen -= SLOW_IR_FCS_SIZE;


				#ifdef DBG_ADD_PKT_ID
					if (addPktIdOn){
						/*
						 *  Remove dbg packet id.
						 */
						rcvBuf->dataLen -= sizeof(USHORT);
						DBGOUT((" RCVing packet %xh **", (UINT)*(USHORT *)(rcvBuf->dataBuf+rcvBuf->dataLen)));
					}
				#endif

				/*
				 *  The packet array is set up with its NDIS_PACKET.
				 *  Now we need to allocate a single NDIS_BUFFER for the
				 *  NDIS_PACKET and set the NDIS_BUFFER  to the part of dataBuf
				 *  that we want to deliver.
				 */
				NdisAllocateBuffer(	&stat, 
									&packetBuf, 
									thisDev->bufferPoolHandle,
									(PVOID)rcvBuf->dataBuf,
									rcvBuf->dataLen); 
				if (stat != NDIS_STATUS_SUCCESS){
					DBGERR(("NdisAllocateBuffer failed"));
					break;
				}
				NdisChainBufferAtFront(rcvBuf->packet, packetBuf);

				/*
				 *  Fix up some other packet fields.
				 */
				NDIS_SET_PACKET_HEADER_SIZE(rcvBuf->packet, SLOW_IR_ADDR_SIZE + SLOW_IR_CONTROL_SIZE);

				DBGPKT(("Indicating rcv packet 0x%x.", (UINT)rcvBuf->packet));
				DBGPRINTBUF(rcvBuf->dataBuf, rcvBuf->dataLen);

				/*  
				 *  Indicate to the protocol that another packet is ready.  
				 *  Set the rcv buffer's state to PENDING first to avoid
				 *  a race condition with NDIS's call to the return packet
				 *  handler.
				 */
				rcvBuf->state = STATE_PENDING;
				NdisMIndicateReceivePacket(thisDev->ndisAdapterHandle, &rcvBuf->packet, 1);
				stat = NDIS_GET_PACKET_STATUS(rcvBuf->packet);			
				if (stat == NDIS_STATUS_PENDING){
					/*
					 *  The packet is being delivered asynchronously.
					 *  Leave the rcv buffer's state as PENDING; we'll
					 *  get a callback when the transfer is complete.
					 *	
					 *  Do NOT step firstRcvBufIndex.
					 *  We don't really need to break out here, 
					 *  but we will anyways just to make things simple.
					 *  This is ok since we get this deferred interrupt callback
					 *  for each packet anyway.  It'll give the protocol a chance
					 *  to catch up.
					 */
					DBGSTAT(("Rcv Pending.  Rcvd %d packets", ++thisDev->packetsRcvd));
				}
				else {
					/*
					 *  If there was an error, we are dropping this packet;
					 *  otherwise, this packet was delivered synchronously. 
					 *  We can free the packet buffer and make this rcv frame
					 *  available.
					 */
					NdisUnchainBufferAtFront(rcvBuf->packet, &packetBuf);
					if (packetBuf){
						NdisFreeBuffer(packetBuf);	
					}	
					rcvBuf->state = STATE_FREE;

					if (stat == NDIS_STATUS_SUCCESS){
						DBGSTAT(("Rcvd %d packets", ++thisDev->packetsRcvd));
					}
					else {
						DBGSTAT(("Dropped %d/%d rcv packets. ", thisDev->packetsDropped++, thisDev->packetsDropped+thisDev->packetsRcvd));
					}
				}

				break;


			default:
				/*
				 *  This should never happen.
				 */
				DBGERR(("Bad rcv buffer state in DPC"));
				break;
		}
		
		/*
		 *  Step the buffer index
		 */
		if (rcvBufIndex == thisDev->lastRcvBufIndex){
			rcvBufIndex = NO_BUF_INDEX;
		}
		else {
			rcvBufIndex = NEXT_RCV_BUF_INDEX(rcvBufIndex);
		}
	}

	DBGOUT(("<== DeliverFullBuffers"));

}
Ejemplo n.º 3
0
INT
LpxProtocolReceivePacket(
	IN NDIS_HANDLE	ProtocolBindingContext,
	IN PNDIS_PACKET	Packet
){
	PDEVICE_CONTEXT	deviceContext;
	PNDIS_BUFFER	ndisFirstBuffer;
	PVOID			firstBuffer;
	UINT		    firstBufferSize;
	UINT			totalBufferSize;
	USHORT		    protocol;
	PNDIS_PACKET	packet = NULL;
	NDIS_STATUS		status;
	INT				pktReferenceCount = 0;
	UINT		    addiLlcHeaderSize = 0;
	PLPX_HEADER		lpxHeader;
	USHORT			lpxHeaderSize;
	UINT			lpxPayload;
	UINT			rawDataOffset;


	DebugPrint( 4, ("ProtocolReceivePacket: Entered\n") );
	
	deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext;

	//
	//	Check to see if the device context is initialized.
	//
	ASSERT( deviceContext->NdisBindingHandle );

	if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) ||
		FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) {

			DebugPrint( 4,("Device is not initialized. Drop packet\n") );

			return 0;
	}

	//
	//	validation
	//
	NdisGetFirstBufferFromPacket(
				Packet,
				&ndisFirstBuffer,
				&firstBuffer,
				&firstBufferSize,
				&totalBufferSize);

	if (firstBufferSize < ETHERNET_HEADER_LENGTH) {

		DebugPrint( 1, ("ProtocolReceivePacket: FirstBufferSize = %x\n", firstBufferSize) );
		return 0;
	}

	protocol = ((PETHERNET_HEADER)firstBuffer)->Type;

	//
	//	Discard 802.2 LLC SNAP field.
	//
	// if Ether Type less than 0x0600 ( 1536 )
	//

	if (NTOHS(protocol) < 0x0600  && 
	    NTOHS(protocol) != 0x0060 && // LOOP: Ethernet Loopback
		NTOHS(protocol) != 0x0200 && // PUP : Xerox PUP packet
		NTOHS(protocol) != 0x0201) { // PUPAP: Xerox PUP address trans packet 

		protocol = *(PUSHORT)((PUCHAR)firstBuffer + ETHERNET_HEADER_LENGTH + LENGTH_8022LLCSNAP - 2);
		if(firstBufferSize >= LENGTH_8022LLCSNAP)
			firstBufferSize -= LENGTH_8022LLCSNAP;
		else {
			DebugPrint( 1, ("ProtocolReceivePacket: Too small first buffer\n") );
			return 0;
		}

		if(totalBufferSize >= LENGTH_8022LLCSNAP)
			totalBufferSize -= LENGTH_8022LLCSNAP;
		else {
			DebugPrint( 1, ("ProtocolReceivePacket: Too small total buffer\n") );
			return 0;
		}
		addiLlcHeaderSize = LENGTH_8022LLCSNAP;
	}

	if (protocol != HTONS(ETH_P_LPX)) {
	
		DebugPrint( 4, ("ProtocolReceivePacket: Type = %x\n", protocol) );
		return 0;
	}
	if(totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + sizeof(LPX_HEADER)) {
		DebugPrint( 1, ("ProtocolReceivePacket: too small packet(1).\n"));
		return 0;
	}

	//
	// Extract LPX header information
	//
	//

	lpxHeader = (PLPX_HEADER)((PBYTE)firstBuffer + ETHERNET_HEADER_LENGTH + addiLlcHeaderSize);
	lpxHeaderSize = sizeof(LPX_HEADER);
	lpxPayload = NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize;

#if __LPX_OPTION_ADDRESSS__

	if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) {
		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
	}

	if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) {
		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
	}

#endif

	if(totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize + lpxPayload) {
		DebugPrint( 1, ("ProtocolReceivePacket: too small packet(2).\n"));
		return 0;
	}

	//
	// DROP PACKET for DEBUGGING!!!!
	//

#if 1 //DBG // Enabled for testing

	if (PacketRxDropRate) {

		PacketRxCountForDrop++;
				
		if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) {
			PLPX_HEADER        lpxHeader = (PLPX_HEADER)((PUCHAR)firstBuffer + addiLlcHeaderSize);
#if 0
			if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) 
				DebugPrint( 1, ("[Drop(%x,%x,%x))]\n", 
								 NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) );
#endif			
			DebugPrint( 1, ("D\n") );

			return 0;
		}
	}

#endif

	ASSERT( addiLlcHeaderSize == 0 );

	DebugPrint( 4, ("ProtocolReceivePacket: TotalBuffSz = %d, FirstBuffSz = %d, LPX_HEADER size = %d\n",
					 totalBufferSize, firstBufferSize, sizeof(LPX_HEADER)) );
	//
	//  If the miniport is out of resources, we can't queue
	//  this packet - make a copy if this is so.
	//
	if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES) {

		UINT			bytesCopied;

		DebugPrint( 1, ("ProtocolReceivePacket: Miniport reported low packet resources.\n"));

		status = RcvPacketAlloc( deviceContext,
								 lpxPayload,
								 &packet );

		if (status == STATUS_SUCCESS) {
			ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS );
			//
			// Copy lpx payload. payload contains only data.
			//
			NdisCopyFromPacketToPacket(
						packet, 0,
						lpxPayload,
						Packet, ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize,
						&bytesCopied);
			ASSERT(lpxPayload == bytesCopied);
		}

		rawDataOffset = 0;
		pktReferenceCount = 0;
	} else {
		PLPX_RESERVED	externalReserved;
		//
		// No need to allocate new NDIS packet and copy data to the new NDIS packet.
		// But, NDIS miniport allocates only 4 * sizeof(PVOID) for protocol reserved context.
		// We should allocate our own.
		//
		packet = Packet;

		status = NdisAllocateMemoryWithTag(&externalReserved, sizeof(LPX_RESERVED), LPX_MEM_TAG_EXTERNAL_RESERVED);
		if(status == NDIS_STATUS_SUCCESS) {

			RtlZeroMemory(externalReserved, sizeof(LPX_RESERVED));

			// By setting the external reserved field, RESERVED() uses external reserved context automatically.
			((PLPX_RESERVED)packet->ProtocolReserved)->ExternalReserved = externalReserved;

			// Initialize LPX reserved context instead of RcvPacketAlloc().
			RESERVED(packet)->Cloned = 0;
			RESERVED(packet)->Type = LPX_PACKET_TYPE_RECEIVE;
			RESERVED(packet)->RecvFlags |= LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT;

			// set data offset
			// Because NDIS miniport allocated the packet, the NDIS packet contains whole raw packet data.
			rawDataOffset = ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize;
			lpxPayload += rawDataOffset;

			// return one reference count indicating LPX will call NdisReturnPackets() once.
			pktReferenceCount = 1;

		}
	}

	if (status != NDIS_STATUS_SUCCESS) {

		return 0;
	}

	//
	// Init LPX reserved context
	//

	LpxCopyEthLpxHeadersToLpxReserved(packet, firstBuffer, protocol, lpxHeader, lpxHeaderSize);
	RESERVED(Packet)->Packet = packet;
	RESERVED(Packet)->RecvTime = CurrentTime();
	RESERVED(Packet)->PacketRawDataLength = lpxPayload;
	RESERVED(Packet)->PacketRawDataOffset = rawDataOffset;

	//
	// Queue to the device context.
	//

	ExInterlockedInsertTailList( &deviceContext->PacketInProgressList,
								 &(RESERVED(Packet)->ListEntry),
								 &deviceContext->PacketInProgressQSpinLock );


	return pktReferenceCount;
}
Ejemplo n.º 4
0
NDIS_STATUS
proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet)
{
#if WORKER_TEST
   MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE);
   return NDIS_STATUS_PENDING;
#else
   KIRQL RaiseOldIrql;
   NDIS_STATUS NdisStatus;

   if(MiniIsBusy(Adapter, NdisWorkItemSend)) {
      MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE);
      return NDIS_STATUS_PENDING;
   }

   if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
   {
        if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
        {
            NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
            (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
             Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
             NdisStatus = NDIS_STATUS_PENDING;
        } else {
            /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
            KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
            {
               NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
               (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
                Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
            }
            KeLowerIrql(RaiseOldIrql);

            NdisStatus = NDIS_GET_PACKET_STATUS(Packet);
            if (NdisStatus == NDIS_STATUS_RESOURCES) {
                MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE);
                NdisStatus = NDIS_STATUS_PENDING;
            }
        }

        if (NdisStatus != NDIS_STATUS_PENDING) {
            MiniWorkItemComplete(Adapter, NdisWorkItemSend);
        }

        return NdisStatus;
   } else {
        if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
        {
            NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
            NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
                          Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags);
            NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
        } else {
            /* Send is called at DISPATCH_LEVEL for all serialized miniports */
            KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
            NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
            NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
                          Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags);
            NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
            KeLowerIrql(RaiseOldIrql);

            if (NdisStatus == NDIS_STATUS_RESOURCES) {
                MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE);
                NdisStatus = NDIS_STATUS_PENDING;
            }
        }

        if (NdisStatus != NDIS_STATUS_PENDING) {
            MiniWorkItemComplete(Adapter, NdisWorkItemSend);
        }

        return NdisStatus;
   }
#endif
}
Ejemplo n.º 5
0
INT
	natpReceivePacketPassThrough(
		IN NDIS_HANDLE ProtocolBindingContext,
		IN PNDIS_PACKET Packet,
		IN FLT_PKT* pFltPkt
		)
{
	PFILTER_ADAPTER pAdapt =(PFILTER_ADAPTER)ProtocolBindingContext;
	NDIS_STATUS Status;
	PNDIS_PACKET MyPacket;
	BOOLEAN Remaining;
	PNDIS_BUFFER		pNewBuffer;

	if (NULL == pAdapt->MiniportHandle || pAdapt->natmDeviceState > NdisDeviceStateD0)
		return 0;
	NdisIMGetCurrentPacketStack(Packet, &Remaining);
	if (NULL == pFltPkt && Remaining){
		Status = NDIS_GET_PACKET_STATUS(Packet);
		NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1);

		return Status != NDIS_STATUS_RESOURCES ? 1 : 0;
    	}

	if(NULL == pFltPkt){

		NdisDprAllocatePacket(
			&Status,
			&MyPacket,
			pAdapt->RcvPP1
			);

		if (Status != NDIS_STATUS_SUCCESS){
			return 0;
		}

		*((PVOID*)&MyPacket->MiniportReserved) = Packet;

		MyPacket->Private.Head = Packet->Private.Head;
		MyPacket->Private.Tail = Packet->Private.Tail;

	}else{

		NdisDprAllocatePacket(
			&Status,
			&MyPacket,
			pAdapt->RcvPP2
			);

		if (Status != NDIS_STATUS_SUCCESS)
			return NDIS_STATUS_NOT_ACCEPTED;

		*((PVOID*)&MyPacket->MiniportReserved) = pFltPkt;

		NdisAllocateBuffer(
			&Status,
			&pNewBuffer,
			pAdapt->RcvBP,
			pFltPkt->pBuf,
			pFltPkt->uLen
			);

		if ( Status != NDIS_STATUS_SUCCESS ){

			NdisReinitializePacket (MyPacket);
			NdisFreePacket (MyPacket);

			return 0;
		}

		NdisChainBufferAtFront(MyPacket, pNewBuffer );
	}
	NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
	NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);

	Status = NDIS_GET_PACKET_STATUS(Packet);

	NDIS_SET_PACKET_STATUS(MyPacket, Status);
	NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));

	if (Status == NDIS_STATUS_RESOURCES){

		natpQueueReceivedPacket(pAdapt, MyPacket, TRUE);
	}else{

		natpQueueReceivedPacket(pAdapt, MyPacket, FALSE);
	}
	
	if (Status == NDIS_STATUS_RESOURCES)
	        NdisDprFreePacket(MyPacket);

	return Status != NDIS_STATUS_RESOURCES ? 1 : 0;
}
Ejemplo n.º 6
0
/******************************************************************************
 *
 *  Name: HandleRxReadyEvent()
 *
 *  Description: Rx ready event handler
 *
 *  Arguments:  PMRVDRV_ADAPTER Adapter
 *    
 *  Return Value:        
 * 
 *  Notes:               
 *
 *****************************************************************************/
VOID
HandleRxReadyEvent(
    IN PMRVDRV_ADAPTER Adapter
)
{
    int           IsRxOK = 0;
    PRxPD         pRxPDCurrent;
    PNDIS_PACKET  pPacket;
    NDIS_STATUS   pStatus;


    DBGPRINT(DBG_RX | DBG_HELP,(L"+HandleRxReadyEvent()\n"));
    pRxPDCurrent = (PRxPD)(Adapter->pRxPD1);


//lykao, 060905, begin
    if (pRxPDCurrent->Status & MRVDRV_RXPD_STATUS_OK)
    {
        Adapter->RcvOK++;
        Adapter->DirectedFramesRcvOK++;
        wlan_compute_rssi(Adapter,pRxPDCurrent);
    }
    else
    {
        DBGPRINT(DBG_RX | DBG_WARNING,(L"WARNING: frame received with bad status\n"));

        //dralee++ 09212005 for error handling 
        pPacket = Adapter->pRxCurPkt;
        Adapter->pRxCurPkt = NULL; 
        if ( pPacket )
            ReturnRxPacketDesc(Adapter,pPacket);
        return;
    }
        
    pPacket = Adapter->pRxCurPkt;
    Adapter->pRxCurPkt = NULL;  

    if (Adapter->MediaConnectStatus == NdisMediaStateConnected)
    {              
        Adapter->ulRxByteInLastPeriod += Adapter->ulRxSize;  

        NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_SUCCESS);

        NdisMIndicateReceivePacket(Adapter->MrvDrvAdapterHdl, &pPacket, 1);
      
        pStatus = NDIS_GET_PACKET_STATUS(pPacket);
        
        if ((pStatus == NDIS_STATUS_RESOURCES) || (pStatus == NDIS_STATUS_SUCCESS))
        {
            // return packet
            DBGPRINT(DBG_RX|DBG_HELP, (L"Packet returned success or resources...\n"));
            ReturnRxPacketDesc(Adapter,pPacket);            
        }
        else
        {
            DBGPRINT(DBG_RX|DBG_ERROR, (L"Packet returned pending...\n"));
        }
    }
    else
    {
        ///pmkcache: bug#16956 ++		
        if (Adapter->bIsReconnectAssociation == TRUE)
        {
            Adapter->isPktPending = TRUE;
            if ( Adapter->pPendedRxPkt )
            {
                NKDbgPrintfW( L"ERROR, a pended RX packet has not been process!!\r\n" );
            }
            Adapter->pPendedRxPkt = pPacket;
            return;
        }
        ///pmkcache: bug#16956 --

        DBGPRINT(DBG_RX|DBG_ERROR, (L"Not connected, packet was dropped...\n"));
        ReturnRxPacketDesc(Adapter,pPacket);
    } 

    return;
}
INT
PtReceivePacket(
	IN	NDIS_HANDLE			ProtocolBindingContext,
	IN	PNDIS_PACKET		Packet
	)
/*++

Routine Description:

	ReceivePacket handler. Called by NDIS if the miniport below supports
	NDIS 4.0 style receives. Re-package the buffer chain in a new packet
	and indicate the new packet to protocols above us. Any context for
	packets indicated up must be kept in the MiniportReserved field.

	NDIS 5.1 - packet stacking - if there is sufficient "stack space" in
	the packet passed to us, we can use the same packet in a receive
	indication.

Arguments:

	ProtocolBindingContext - Pointer to our adapter structure.
	Packet - Pointer to the packet

Return Value:

	== 0 -> We are done with the packet
	!= 0 -> We will keep the packet and call NdisReturnPackets() this
			many times when done.
--*/
{
	PADAPT				pAdapt =(PADAPT)ProtocolBindingContext;
	NDIS_STATUS			Status;
	PNDIS_PACKET		MyPacket;
	BOOLEAN				Remaining;
	//------------------------------WestChamber---------------------------------
			BOOLEAN result=WestChamberReceiverMain(Packet,pAdapt);
			if(result==FALSE) {
				//Simply drop the packet.
				//return NDIS_STATUS_NOT_ACCEPTED;
				return 0;		//Thanks to Albert Jin.
			}
	//------------------------------WestChamber---------------------------------
	//
	// Drop the packet silently if the upper miniport edge isn't initialized
	//
	if (!pAdapt->MiniportHandle)
	{
		  return 0;
	}

#ifdef NDIS51
	//
	// Check if we can reuse the same packet for indicating up.
	// See also: PtReceive(). 
	//
	(VOID)NdisIMGetCurrentPacketStack(Packet, &Remaining);
	if (Remaining)
	{
		//
		// We can reuse "Packet". Indicate it up and be done with it.
		//
		Status = NDIS_GET_PACKET_STATUS(Packet);
		NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1);
		return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
	}
#endif // NDIS51

	//
	// Get a packet off the pool and indicate that up
	//
	NdisDprAllocatePacket(&Status,
						   &MyPacket,
						   pAdapt->RecvPacketPoolHandle);

	if (Status == NDIS_STATUS_SUCCESS)
	{
		PRECV_RSVD			RecvRsvd;

		RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved);
		RecvRsvd->OriginalPkt = Packet;

		MyPacket->Private.Head = Packet->Private.Head;
		MyPacket->Private.Tail = Packet->Private.Tail;

		//
		// Get the original packet (it could be the same packet as the one
		// received or a different one based on the number of layered miniports
		// below) and set it on the indicated packet so the OOB data is visible
		// correctly to protocols above us.
		//
		NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));

		//
		// Set Packet Flags
		//
		NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);

		Status = NDIS_GET_PACKET_STATUS(Packet);

		NDIS_SET_PACKET_STATUS(MyPacket, Status);
		NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));

		NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);

		//
		// Check if we had indicated up the packet with NDIS_STATUS_RESOURCES
		// NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket) for this since
		// it might have changed! Use the value saved in the local variable.
		//
		if (Status == NDIS_STATUS_RESOURCES)
		{
			//
			// Our ReturnPackets handler will not be called for this packet.
			// We should reclaim it right here.
			//
			NdisDprFreePacket(MyPacket);
		}

		return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
	}
	else
	{
		//
		// We are out of packets. Silently drop it.
		//
		return(0);
	}
}
Ejemplo n.º 8
0
INT
LpxProtocolReceivePacket (
	IN NDIS_HANDLE	ProtocolBindingContext,
	IN PNDIS_PACKET	Packet
	)
{
	PDEVICE_CONTEXT	deviceContext;

	PLPX_RESERVED	reserved = NULL;	

	PNDIS_BUFFER	ndisFirstBuffer;
	PVOID			firstBuffer;
	UINT		    firstBufferSize;
	UINT			totalBufferSize;
	PNDIS_PACKET	packet = NULL;
	NDIS_STATUS		status;
	INT				pktReferenceCount = 0;
	UINT		    addiLlcHeaderSize = 0;
	PLPX_HEADER		lpxHeader;
	USHORT			lpxHeaderSize;
	UINT			lpxPayload;
	UINT			rawDataOffset;
	ETHERNET_HEADER	ethernetHeader;

	DebugPrint( 4, ("ProtocolReceivePacket: Entered\n") );
	
	deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext;

	//	Check to see if the device context is initialized.

	if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) {

		DebugPrint( 1, ("Device is not initialized. Drop packet\n") );

		return NDIS_STATUS_NOT_RECOGNIZED;
	}

	NDAS_ASSERT( deviceContext->NdisBindingHandle );

	//	validation

#ifndef NTDDI_VERSION

	NdisGetFirstBufferFromPacket( Packet,
								  &ndisFirstBuffer,
								  &firstBuffer,
								  &firstBufferSize,
								  &totalBufferSize );
#else

	firstBufferSize = 0;
	
	NdisGetFirstBufferFromPacketSafe( Packet,
									  &ndisFirstBuffer,
									  &firstBuffer,
									  &firstBufferSize,
									  &totalBufferSize,
									  HighPagePriority );
#endif

	if (firstBufferSize < ETHERNET_HEADER_LENGTH) {

		NDAS_ASSERT(FALSE);

		DebugPrint( 2, ("ProtocolReceivePacket: FirstBufferSize = %x\n", firstBufferSize) );
		return 0;
	}

	RtlCopyMemory( &ethernetHeader, firstBuffer, ETHERNET_HEADER_LENGTH );

	if (ethernetHeader.DestinationAddress[5] != 0xFF) {

		DebugPrint( 3, ("LpxProtocolReceivePacket: Type = %X\n", ethernetHeader.Type) );	
	}

	//	Discard 802.2 LLC SNAP field.
	//
	// if Ether Type less than 0x0600 ( 1536 )

	if (NTOHS(ethernetHeader.Type)  < 0x0600 && 
		NTOHS(ethernetHeader.Type) != 0x0060 && // LOOP:  Ethernet Loopback
		NTOHS(ethernetHeader.Type) != 0x0200 && // PUP :  Xerox PUP packet
		NTOHS(ethernetHeader.Type) != 0x0201) { // PUPAP: Xerox PUP address trans packet 

		RtlCopyMemory( &ethernetHeader, 
					   (PUCHAR)firstBuffer + ETHERNET_HEADER_LENGTH + LENGTH_8022LLCSNAP - 2, 
					   ETHERNET_HEADER_LENGTH );

		if (firstBufferSize >= LENGTH_8022LLCSNAP) {

			firstBufferSize -= LENGTH_8022LLCSNAP;
		
		} else {

			DebugPrint( 2, ("ProtocolReceivePacket: Too small first buffer\n") );
			return 0;
		}

		if (totalBufferSize >= LENGTH_8022LLCSNAP) {

			totalBufferSize -= LENGTH_8022LLCSNAP;
		
		} else {

			DebugPrint( 2, ("ProtocolReceivePacket: Too small total buffer\n") );
			return 0;
		}

		addiLlcHeaderSize = LENGTH_8022LLCSNAP;

		NDAS_ASSERT( ethernetHeader.Type != HTONS(ETH_P_LPX) );
	}

	if (ethernetHeader.Type != HTONS(ETH_P_LPX)) {
	
		DebugPrint( 4, ("ProtocolReceivePacket: Type = %x\n", ethernetHeader.Type) );
		return 0;
	}

	if (totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + sizeof(LPX_HEADER)) {

		DebugPrint( 2, ("ProtocolReceivePacket: too small packet(1).\n"));
		return 0;
	}

	// DROP PACKET for DEBUGGING!!!!

	if (PacketRxDropRate) {

		PacketRxCountForDrop++;
				
		if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) {

			PLPX_HEADER        lpxHeader = (PLPX_HEADER)((PUCHAR)firstBuffer + addiLlcHeaderSize);

			if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) {

				DebugPrint( 6, ("[Drop(%x,%x,%x))]\n", 
								 NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) );
			}

			DebugPrint( 2, ("D\n") );

			return 0;
		}
	}

	if (!(RtlEqualMemory(ethernetHeader.DestinationAddress, deviceContext->LocalAddress.Address, ETHERNET_ADDRESS_LENGTH) ||
		  RtlEqualMemory(ethernetHeader.DestinationAddress, LpxBroadcastAddress, ETHERNET_ADDRESS_LENGTH))) {

		DebugPrint( 4, ("LpxProtocolReceivePacket, %02x%02x%02x%02x%02x%02x\n",
						 deviceContext->LocalAddress.Address[0], deviceContext->LocalAddress.Address[1], 
						 deviceContext->LocalAddress.Address[2], deviceContext->LocalAddress.Address[3], 
						 deviceContext->LocalAddress.Address[4], deviceContext->LocalAddress.Address[5]) );

		DebugPrint( 4, ("LpxProtocolReceivePacket, %02x%02x%02x%02x%02x%02x\n",
						 ethernetHeader.DestinationAddress[0], ethernetHeader.DestinationAddress[1], 
						 ethernetHeader.DestinationAddress[2], ethernetHeader.DestinationAddress[3], 
						 ethernetHeader.DestinationAddress[4], ethernetHeader.DestinationAddress[5]) );

		return 0;
	}

	// Extract LPX header information

	lpxHeader = (PLPX_HEADER)((PBYTE)firstBuffer + ETHERNET_HEADER_LENGTH + addiLlcHeaderSize);
	lpxHeaderSize = sizeof(LPX_HEADER);
	lpxPayload = NTOHS((UINT16)(lpxHeader->PacketSize & ~LPX_TYPE_MASK)) - lpxHeaderSize;

	if (lpxHeader->DestinationPort == NTOHS(LPXRP_HIX_PORT)) {

		DebugPrint( 1, ("[LPX] LpxProtocolReceivePacket: DataGram packet arrived.\n") );
	}

#if __LPX_OPTION_ADDRESSS__

	if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) {

		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
	}

	if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) {

		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
	}

#endif

	if (totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize + lpxPayload) {

		DebugPrint( 2, ("ProtocolReceivePacket: too small packet(2).\n") );

		return 0;
	}

	NDAS_ASSERT( addiLlcHeaderSize == 0 );

	DebugPrint( 4, ("ProtocolReceivePacket: TotalBuffSz = %d, FirstBuffSz = %d, LPX_HEADER size = %d\n",
					 totalBufferSize, firstBufferSize, sizeof(LPX_HEADER)) );

	//  If the miniport is out of resources, we can't queue
	//  this packet - make a copy if this is so.

	NDAS_ASSERT( sizeof(ZeroProtocolReserved) == PROTOCOL_RESERVED_OFFSET );

	if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES ||
		!RtlEqualMemory(&Packet->ProtocolReserved[PROTOCOL_RESERVED_OFFSET], ZeroProtocolReserved, sizeof(ZeroProtocolReserved))) {

		UINT bytesCopied;
		INT  i;

		for (i=0; i<16; i++) {

			DebugPrint( 1, ("Packet->ProtocolReserved[%d] = %d\n", i, Packet->ProtocolReserved[i]) );
		}

		NDAS_ASSERT(FALSE);

		DebugPrint( 2, ("ProtocolReceivePacket: Miniport reported low packet resources.\n") );

		status = RcvPacketAlloc( deviceContext, lpxPayload, &packet );

		if (status == STATUS_SUCCESS) {

			NDAS_ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS );

			// Copy lpx payload. payload contains only data.

			NdisCopyFromPacketToPacket( packet, 
										0,
										lpxPayload,
										Packet, 
										ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize,
										&bytesCopied
										);

			NDAS_ASSERT( lpxPayload == bytesCopied );
		}

		rawDataOffset = 0;
		pktReferenceCount = 0;
	
	} else {
	
		PLPX_RESERVED externalReserved;

		// No need to allocate new NDIS packet and copy data to the new NDIS packet.
		// But, NDIS miniport allocates only 4 * sizeof(PVOID) for protocol reserved context.
		// We should allocate our own.

		packet = Packet;

		status = NdisAllocateMemoryWithTag( &externalReserved, sizeof(LPX_RESERVED), LPX_MEM_TAG_EXTERNAL_RESERVED );

		if (status == NDIS_STATUS_SUCCESS) {

			RtlZeroMemory( externalReserved, sizeof(LPX_RESERVED) );

			// By setting the external reserved field, LpxGetReserved() uses external reserved context automatically.

			((PLPX_RESERVED)(&packet->ProtocolReserved[PROTOCOL_RESERVED_OFFSET]))->ExternalReserved = externalReserved;

			reserved = LpxGetReserved(packet);

			// Initialize LPX reserved context instead of RcvPacketAlloc().

			reserved->Cloned = 0;
			reserved->Type = LPX_PACKET_TYPE_RECEIVE;
			reserved->RecvFlags |= LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT;

			// set data offset
			// Because NDIS miniport allocated the packet, the NDIS packet contains whole raw packet data.

			rawDataOffset = ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize;
			lpxPayload += rawDataOffset;

			// return one reference count indicating LPX will call NdisReturnPackets() once.

			pktReferenceCount = 1;
		}
	}

	if (status != NDIS_STATUS_SUCCESS) {

		DebugPrint( 2, ("ProtocolReceivePacket: status != NDIS_STATUS_SUCCESS\n") );
		return 0;
	}

	// Init LPX reserved context

	LpxCopyEthLpxHeadersToLpxReserved( packet, firstBuffer, ethernetHeader.Type, lpxHeader, lpxHeaderSize );

	reserved = LpxGetReserved(packet);

	reserved->Packet = packet;
	reserved->RecvTime = NdasCurrentTime();
	reserved->PacketRawDataLength = lpxPayload;
	reserved->PacketRawDataOffset = rawDataOffset;

	// Queue to the device context.

	ExInterlockedInsertTailList( &deviceContext->PacketInProgressList,
								 &(reserved->ListEntry),
								 &deviceContext->PacketInProgressQSpinLock );

	return pktReferenceCount;
}
/*----------------------------------------------------------------------------*/
WLAN_STATUS kalRxIndicatePkts(IN P_GLUE_INFO_T prGlueInfo, IN PVOID apvPkts[], IN UINT_32 ucPktNum)
{
	NDIS_STATUS arStatus[CFG_RX_MAX_PKT_NUM];
	UINT_32 u4Idx;

	for (u4Idx = 0; u4Idx < ucPktNum; u4Idx++) {
		UINT_32 i, pivot;
		PVOID pvTmp;

		if (NDIS_GET_PACKET_STATUS((PNDIS_PACKET) apvPkts[u4Idx]) == NDIS_STATUS_RESOURCES) {
			pivot = u4Idx;
			for (i = u4Idx + 1; i < ucPktNum; i++) {
				if (NDIS_GET_PACKET_STATUS((PNDIS_PACKET) apvPkts[i]) !=
				    NDIS_STATUS_RESOURCES) {
					pvTmp = apvPkts[pivot];
					apvPkts[pivot] = apvPkts[i];
					apvPkts[i] = pvTmp;
					pivot++;
				}
			}
			break;
		}
	}

	for (u4Idx = 0; u4Idx < ucPktNum; u4Idx++) {
		arStatus[u4Idx] = NDIS_GET_PACKET_STATUS((PNDIS_PACKET) apvPkts[u4Idx]);
		if (arStatus[u4Idx] == NDIS_STATUS_SUCCESS) {
			/* 4 Increase the Pending Count before calling NdisMIndicateReceivePacket(). */
			InterlockedIncrement(&prGlueInfo->i4RxPendingFrameNum);
		}
	}

	NdisMIndicateReceivePacket(prGlueInfo->rMiniportAdapterHandle,
				   (PPNDIS_PACKET) apvPkts, (UINT) ucPktNum);

	for (u4Idx = 0; u4Idx < ucPktNum; u4Idx++) {

		/* 4 <1> Packets be retained. */
		if (arStatus[u4Idx] != NDIS_STATUS_SUCCESS) {
			PNDIS_PACKET prNdisPacket = (PNDIS_PACKET) apvPkts[u4Idx];
			PNDIS_BUFFER prNdisBuf = (PNDIS_BUFFER) NULL;

			ASSERT(prNdisPacket);

			NdisUnchainBufferAtBack(prNdisPacket, &prNdisBuf);

			if (prNdisBuf) {
				NdisFreeBuffer(prNdisBuf);
			}
#if DBG
			else {
				ASSERT(0);
			}
#endif				/* DBG */

			/* Reinitialize the packet descriptor for reuse. */
			NdisReinitializePacket(prNdisPacket);

#if CETK_NDIS_PERFORMANCE_WORKAROUND
			{
				PUINT_32 pu4Dummy;
				pu4Dummy = (PUINT_32) prNdisPacket->ProtocolReserved;
				*pu4Dummy = 0;
			}
#endif				/* CETK_NDIS_PERFORMANCE_WORKAROUND */

		}
	}

	return WLAN_STATUS_SUCCESS;
}				/* kalIndicatePackets */