Beispiel #1
0
/************************************************************
Function called by NDIS to indicate that the data transfer
is finished
************************************************************/
VOID NDIS_API
PacketSendComplete(	IN NDIS_HANDLE	ProtocolBindingContext,
					IN PNDIS_PACKET	pPacket,
					IN NDIS_STATUS	Status
   )
{
	PNDIS_BUFFER 		pNdisBuffer;
	PPACKET_RESERVED	Reserved = (PPACKET_RESERVED) pPacket->ProtocolReserved;

	TRACE_ENTER( "SendComplete" );
	
	NdisUnchainBufferAtFront( pPacket, &pNdisBuffer );
	if ( pNdisBuffer )
		NdisFreeBuffer( pNdisBuffer );
		
	VWIN32_DIOCCompletionRoutine( Reserved->lpoOverlapped->O_Internal );
		
	PacketPageUnlock( Reserved->lpBuffer, Reserved->cbBuffer );
	PacketPageUnlock( Reserved->lpcbBytesReturned, sizeof(DWORD) );
	PacketPageUnlock( Reserved->lpoOverlapped, sizeof(OVERLAPPED) );
	
	NdisReinitializePacket(pPacket);
		
	NdisFreePacket(pPacket);

	TRACE_LEAVE( "SendComplete" );
	return;
}
Beispiel #2
0
/*
 *************************************************************************
 *  ReturnPacketHandler
 *************************************************************************
 *
 *  When NdisMIndicateReceivePacket returns asynchronously, 
 *  the protocol returns ownership of the packet to the miniport via this function.
 *
 */
VOID ReturnPacketHandler(NDIS_HANDLE MiniportAdapterContext, PNDIS_PACKET Packet)
{
	IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
	UINT rcvBufIndex;

	DBGOUT(("ReturnPacketHandler(0x%x)", (UINT)MiniportAdapterContext));

	/*
	 *  The rcv buffer index is cached in the MiniportReserved field of the packet.
	 */
	rcvBufIndex = *(UINT *)Packet->MiniportReserved;

	if (rcvBufIndex < NUM_RCV_BUFS){
		if (thisDev->rcvBufs[rcvBufIndex].state == STATE_PENDING){
			PNDIS_BUFFER ndisBuf;

			DBGPKT(("Reclaimed rcv packet 0x%x.", (UINT)Packet));

			NdisUnchainBufferAtFront(Packet, &ndisBuf);
			if (ndisBuf){
				NdisFreeBuffer(ndisBuf);
			}

			thisDev->rcvBufs[rcvBufIndex].state = STATE_FREE;
		}
		else {
			DBGERR(("Packet in ReturnPacketHandler was not PENDING."));
		}
	}
	else {
		DBGERR(("Bad rcvBufIndex (from corrupted MiniportReserved) in ReturnPacketHandler."));
	}

	
}
Beispiel #3
0
void
CAR6KMini::ReturnPacket(
	IN PNDIS_PACKET Packet)
//
//  After the miniport passes packets up to NDIS via
//  NdisMIndicateReceivePackets, NDIS will some time later
//  return those packets (one at a time) to the miniport
//  by calling this ReturnPacket handler.
//
{
	NDIS_BUFFER *pBuffer;
	A_STATUS status = A_OK;

	// Remove the NDIS_BUFFER from the packet (should be exactly 1 buffer)
	NdisUnchainBufferAtFront(Packet, &pBuffer);

	// Return the NDIS_PACKET to our pool
	NdisFreePacket(Packet);

	// Return the pb containing the NDIS_BUFFER to the HTC layer
	// to receive a new packet
	ndis_mini_buf_t *pb = (ndis_mini_buf_t *)((PBYTE)pBuffer - offsetof(ndis_mini_buf_t, NdisBuffer));
	status = HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb);

	if ( status != A_OK ) {
		//HTC did'nt accept the buffer. Free it.
		a_netbuf_free(pb);
	}
}
Beispiel #4
0
VOID NDIS_API PacketTransferDataComplete(IN NDIS_HANDLE  ProtocolBindingContext,
                                         IN PNDIS_PACKET pPacket,
                                         IN NDIS_STATUS  Status,
                                         IN UINT         BytesTransfered)
{
  // upcall when no more data available

  POPEN_INSTANCE Open = (POPEN_INSTANCE)ProtocolBindingContext;
  PPACKET_RESERVED pReserved = (PPACKET_RESERVED)(pPacket->ProtocolReserved);
  OVERLAPPED * pOverlap = (OVERLAPPED *)(pReserved->lpoOverlapped);
  PNDIS_BUFFER pNdisBuffer;


  // free buffer descriptor
  NdisUnchainBufferAtFront(pPacket, &pNdisBuffer);
  if (pNdisBuffer)
    NdisFreeBuffer(pNdisBuffer);

  // set total bytes returned
  BytesTransfered += ETHERNET_HEADER_LENGTH;
  *pReserved->lpcbBytesReturned += BytesTransfered;

  pOverlap->O_InternalHigh = *(pReserved->lpcbBytesReturned);

  // The internal member of overlapped structure contains
  // a pointer to the event structure that will be signalled,
  // resuming the execution of the waitng GetOverlappedResult
  // call.
  VWIN32_DIOCCompletionRoutine(pOverlap->O_Internal);

  // Unlock buffers   
  PacketPageUnlock(pReserved->lpBuffer, pReserved->cbBuffer);
  PacketPageUnlock(pReserved->lpcbBytesReturned, sizeof(DWORD));
  PacketPageUnlock(pReserved->lpoOverlapped, sizeof(OVERLAPPED));

  // recycle the packet
  NdisReinitializePacket(pPacket);

  // Put the packet on the free queue
  NdisFreePacket(pPacket);
}
Beispiel #5
0
// Release the packet buffer
void NeoFreePacketBuffer(PACKET_BUFFER *p)
{
	// Validate arguments
	if (p == NULL)
	{
		return;
	}

	// Detach the buffer from the packet
	NdisUnchainBufferAtFront(p->NdisPacket, &p->NdisBuffer);
	// Release the packet
	NdisFreePacket(p->NdisPacket);
	// Release the packet pool
	NdisFreePacketPool(p->PacketPool);
	// Release the buffer
	NdisFreeBuffer(p->NdisBuffer);
	// Release the memory
	NeoFree(p->Buf);
	// Release the buffer pool
	NdisFreeBufferPool(p->BufferPool);
	// Release the memory
	NeoFree(p);
}
Beispiel #6
0
VOID NDIS_API PacketSendComplete(IN NDIS_HANDLE  ProtocolBindingContext,
                                 IN PNDIS_PACKET pPacket,
                                 IN NDIS_STATUS  Status)
{
  // upcall on completion of send

  PNDIS_BUFFER     pNdisBuffer;
  PPACKET_RESERVED Reserved = (PPACKET_RESERVED)pPacket->ProtocolReserved;

  
  // free buffer descriptor
  NdisUnchainBufferAtFront(pPacket, &pNdisBuffer);
  
  if (pNdisBuffer)
    NdisFreeBuffer(pNdisBuffer);
  
  // return status
  Reserved->lpoOverlapped->O_InternalHigh = Status;
  
  // The internal member of overlapped structure contains
  // a pointer to the event structure that will be signalled,
  // resuming the execution of the waiting GetOverlappedResult
  // call.
  VWIN32_DIOCCompletionRoutine(Reserved->lpoOverlapped->O_Internal);
  
  // Unlock buffers	
  PacketPageUnlock(Reserved->lpBuffer, Reserved->cbBuffer);
  PacketPageUnlock(Reserved->lpcbBytesReturned, sizeof(DWORD));
  PacketPageUnlock(Reserved->lpoOverlapped, sizeof(OVERLAPPED));
  
  // recycle the packet
  NdisReinitializePacket(pPacket);
  
  // Put the packet back on the free list
  NdisFreePacket(pPacket);
}
Beispiel #7
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"));

}
Beispiel #8
0
VOID
StSendDatagramCompletion(
    IN PTP_ADDRESS Address,
    IN PNDIS_PACKET NdisPacket,
    IN NDIS_STATUS NdisStatus
    )

/*++

Routine Description:

    This routine is called as an I/O completion handler at the time a
    StSendUIMdlFrame send request is completed.  Because this handler is only
    associated with StSendUIMdlFrame, and because StSendUIMdlFrame is only
    used with datagrams and broadcast datagrams, we know that the I/O being
    completed is a datagram.  Here we complete the in-progress datagram, and
    start-up the next one if there is one.

Arguments:

    Address - Pointer to a transport address on which the datagram
        is queued.

    NdisPacket - pointer to the NDIS packet describing this request.

Return Value:

    none.

--*/

{
    PTP_REQUEST Request;
    PLIST_ENTRY p;
    KIRQL oldirql;
    PNDIS_BUFFER HeaderBuffer;

    UNREFERENCED_PARAMETER(NdisPacket);

    StReferenceAddress ("Complete datagram", Address);

    //
    // Dequeue the current request and return it to the client.  Release
    // our hold on the send datagram queue.
    //
    // *** There may be no current request, if the one that was queued
    //     was aborted or timed out.
    //

    ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
    p = RemoveHeadList (&Address->SendDatagramQueue);

    if (p != &Address->SendDatagramQueue) {

        RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);

        Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);

        //
        // Strip off and unmap the buffers describing data and header.
        //

        NdisUnchainBufferAtFront (Address->Packet->NdisPacket, &HeaderBuffer);

        // drop the rest of the packet

        NdisReinitializePacket (Address->Packet->NdisPacket);

        NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL;
        NdisChainBufferAtFront (Address->Packet->NdisPacket, HeaderBuffer);

        //
        // Ignore NdisStatus; datagrams always "succeed".
        //

        StCompleteRequest (Request, STATUS_SUCCESS, Request->Buffer2Length);

        ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
        Address->Flags &= ~ADDRESS_FLAGS_SEND_IN_PROGRESS;
        RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);

        //
        // Send more datagrams on the Address if possible.
        //

        StSendDatagramsOnAddress (Address);       // do more datagrams.

    } else {

        Address->Flags &= ~ADDRESS_FLAGS_SEND_IN_PROGRESS;
        RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);

    }

    StDereferenceAddress ("Complete datagram", Address);

} /* StSendDatagramCompletion */
Beispiel #9
0
VOID
PacketFree2 (
	IN PNDIS_PACKET		Packet
	)
{
	PLPX_RESERVED	reserved = RESERVED(Packet);
	PUCHAR			packetData;
	PNDIS_BUFFER	pNdisBuffer;
	UINT			uiLength;
	LONG			clone;
	LONG			BufferSeq;
	BOOLEAN			allocMiniport = FALSE;
	PLPX_RESERVED	externalReserved;


	DebugPrint( 3, ("PacketFree reserved->type = %d\n", reserved->Type) );
	ASSERT( Packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS );

	
	switch (reserved->Type) {

	case LPX_PACKET_TYPE_SEND:

		clone = InterlockedDecrement( &reserved->Cloned );
		
		if(clone >= 0) {
		
			return;
		}
	
		pNdisBuffer = NULL;
		BufferSeq = 0;
		NdisUnchainBufferAtFront( Packet, &pNdisBuffer );

		while (pNdisBuffer) {

			//
			//	Assuming the first data buffer comes from user application
			//			the others are created in LPX for padding, etc.
			//	Free the memory of the others.
			//
			
			if (BufferSeq == 0) {

#if DBG
				NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority );
				ASSERT( packetData == (PCHAR)&RESERVED(Packet)->EthernetHeader );
#endif

			} else if (BufferSeq == 1) {

				// UserBuffer

			} else if (BufferSeq == 2) {

				// Padding
					
				NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority );
				LpxFreeMemoryWithLpxTag( packetData );
			
			} else {

				ASSERT( FALSE );
			}

			NdisFreeBuffer( pNdisBuffer );

			pNdisBuffer = NULL;
			NdisUnchainBufferAtFront( Packet, &pNdisBuffer );
			BufferSeq ++;
		}
		
		if (reserved->IrpSp != NULL) {
			
			PIRP _Irp = IRP_SEND_IRP( reserved->IrpSp );

			ASSERT( reserved->NdisStatus == NDIS_STATUS_SUCCESS || reserved->NdisStatus == NDIS_STATUS_NOT_ACCEPTED || !NT_SUCCESS(reserved->NdisStatus) );

			if (!NT_SUCCESS(reserved->NdisStatus)) {

				_Irp->IoStatus.Status = reserved->NdisStatus;
			}

			//INC_IRP_RETRANSMITS( _Irp, reserved->Retransmits );

			LpxDereferenceSendIrp( "Destroy packet", reserved->IrpSp, RREF_PACKET );
		
		} else {
		
			DebugPrint( 3, ("[LPX] PacketFree: No IrpSp\n") ) ;
		}

		break;

	case LPX_PACKET_TYPE_RECEIVE:

		//
		// If the packet allocated by NIC miniport, break here.
		//
		if(RESERVED(Packet)->RecvFlags & LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT) {
			allocMiniport = TRUE;
			break;
		}

		pNdisBuffer = NULL;	

		NdisUnchainBufferAtFront( Packet, &pNdisBuffer );

#if __LPX_STATISTICS__
		{
			LARGE_INTEGER systemTime;

			KeQuerySystemTime( &systemTime );

			RESERVED(Packet)->DeviceContext->NumberOfRecvPackets ++;
			RESERVED(Packet)->DeviceContext->FreeTimeOfRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart;
			RESERVED(Packet)->DeviceContext->BytesOfRecvPackets.QuadPart += sizeof(LPX_HEADER) + RESERVED(Packet)->PacketRawDataLength;

			if (RESERVED(Packet)->PacketRawDataLength) {

				RESERVED(Packet)->DeviceContext->NumberOfLargeRecvPackets ++;
				RESERVED(Packet)->DeviceContext->FreeTimeOfLargeRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart;
				RESERVED(Packet)->DeviceContext->BytesOfLargeRecvPackets.QuadPart += sizeof(LPX_HEADER) + RESERVED(Packet)->PacketRawDataLength;
			
			} else {

				RESERVED(Packet)->DeviceContext->NumberOfSmallRecvPackets ++;
				RESERVED(Packet)->DeviceContext->FreeTimeOfSmallRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart;
				RESERVED(Packet)->DeviceContext->BytesOfSmallRecvPackets.QuadPart += sizeof(LPX_HEADER);
			}
		}
#endif

		if (pNdisBuffer) {

			NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority );
			
			LpxFreeMemoryWithLpxTag( packetData );
			NdisFreeBuffer( pNdisBuffer );
		}

		break;
	default:
		ASSERT(FALSE);
		return;
	}

	//
	// Free external protocol reserved context.
	//

	externalReserved = ((PLPX_RESERVED)(Packet->ProtocolReserved))->ExternalReserved;
	if(externalReserved) {
		NdisFreeMemory(externalReserved, sizeof(LPX_RESERVED), 0);
	}

	ASSERT( Packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS );
	if(allocMiniport) {
		//
		// Return the packet allocated by NIC miniport
		//
		NdisReturnPackets(&Packet, 1);
	} else {

		NdisFreePacket( Packet );

		InterlockedDecrement( &NumberOfAllockPackets );
		DebugPrint( 3, ("Packet REALLY Freed NumberOfAllockPackets = %d\n", NumberOfAllockPackets) );

	}

}
Beispiel #10
0
NDIS_STATUS
NdisuioReceive(
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN NDIS_HANDLE                  MacReceiveContext,
    IN PVOID                        pHeaderBuffer,
    IN UINT                         HeaderBufferSize,
    IN PVOID                        pLookaheadBuffer,
    IN UINT                         LookaheadBufferSize,
    IN UINT                         PacketSize
    )
/*++

Routine Description:

    Our protocol receive handler called by NDIS, typically if we have
    a miniport below that doesn't indicate packets.

    We make a local packet/buffer copy of this data, queue it up, and
    kick off the read service routine.

Arguments:

    ProtocolBindingContext - pointer to open context
    MacReceiveContext - for use in NdisTransferData
    pHeaderBuffer - pointer to data header
    HeaderBufferSize - size of the above
    pLookaheadBuffer - pointer to buffer containing lookahead data
    LookaheadBufferSize - size of the above
    PacketSize - size of the entire packet, minus header size.

Return Value:

    NDIS_STATUS_NOT_ACCEPTED - if this packet is uninteresting
    NDIS_STATUS_SUCCESS - if we processed this successfully

--*/
{
    PNDISUIO_OPEN_CONTEXT   pOpenContext;
    NDIS_STATUS             Status;
    PNDISUIO_ETH_HEADER     pEthHeader;
    PNDIS_PACKET            pRcvPacket;
    PUCHAR                  pRcvData;
    UINT                    BytesTransferred;
    PNDIS_BUFFER            pOriginalNdisBuffer, pPartialNdisBuffer;
    PIRP					pIrp;
    PLIST_ENTRY				pIrpEntry;
    ULONG					BytesRemaining; // at pDst
	PPACKET_GROUP			pGroup;

	//ULONG                   pDst;
	
    pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
    NUIO_STRUCT_ASSERT(pOpenContext, oc);
    pRcvPacket = NULL;
    pRcvData = NULL;
    Status = NDIS_STATUS_SUCCESS;

    DEBUGP(DL_LOUD, ("Receive: Open %p, LookaheadBufferSize %d, PacketSize %d\n",
		pOpenContext, LookaheadBufferSize, PacketSize));
    
	NdisInterlockedAddLargeStatistic((PLARGE_INTEGER)&pOpenContext->ReceivedPackets, 1);

	do
    {
        if (HeaderBufferSize != sizeof(NDISUIO_ETH_HEADER))
        {
            Status = NDIS_STATUS_NOT_ACCEPTED;
            break;
        }

        pEthHeader = (PNDISUIO_ETH_HEADER)pHeaderBuffer;

		NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);

		//
		// Someone is reading, and this is the first packet.
		//
		if (!NUIO_IS_LIST_EMPTY(&pOpenContext->PendedReads) &&
			NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
		{
			//
			//  Get the first pended Read IRP
			//
			pIrpEntry = pOpenContext->PendedReads.Flink;
			pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry);
			
			//
			// We don't have to worry about the situation where the IRP is cancelled
			// after we remove it from the queue and before we reset the cancel
			// routine because the cancel routine has been coded to cancel an IRP
			// only if it's in the queue.
			//
			IoSetCancelRoutine(pIrp, NULL);

			NUIO_REMOVE_ENTRY_LIST(pIrpEntry);
			
			pOpenContext->PendedReadCount--;

			NUIO_RELEASE_LOCK(&pOpenContext->Lock);

			NUIO_DEREF_OPEN(pOpenContext);  // Service: dequeue rcv packet

			//
			//  Copy as much data as possible from the receive packet to
			//  the IRP MDL.
			//
#ifndef WIN9X
			pGroup = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
			//NUIO_ASSERT(pDst != NULL);  // since it was already mapped
#else
			pGroup = MmGetSystemAddressForMdl(pIrp->MdlAddress);  // Win9x
#endif
			BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress);
			
			BytesRemaining -= sizeof(PACKET_GROUP);

			//
			//  copy the ethernet header into the actual readbuffer
			//
			NdisMoveMappedMemory(pGroup->Data, pHeaderBuffer, HeaderBufferSize);
			
			if (PacketSize == LookaheadBufferSize)
			{
				BytesTransferred = MIN(LookaheadBufferSize, BytesRemaining);

				NdisCopyLookaheadData(pGroup->Data + HeaderBufferSize,
					pLookaheadBuffer,
					BytesTransferred,
					pOpenContext->MacOptions);

				pGroup->Length = BytesTransferred + HeaderBufferSize;
				
				pIrp->IoStatus.Information = pGroup->Length + sizeof(PACKET_GROUP);
				pIrp->IoStatus.Status = STATUS_SUCCESS;				
		
				DEBUGP(DL_LOUD, ("Receive: %d bytes\n", pIrp->IoStatus.Information));
		
				IoCompleteRequest(pIrp, IO_NO_INCREMENT);
			}
			else
			{
				BytesTransferred = 0;

				NdisAllocatePacket(
					&Status,
					&pRcvPacket,
					pOpenContext->RecvBufferPool
					);
				
				if (Status != NDIS_STATUS_SUCCESS)
					goto ERROR;
				
				//
				//  Allocate an MDL to map the portion of the buffer following the
				//  header
				//
				pPartialNdisBuffer = IoAllocateMdl(pGroup->Data, BytesRemaining, FALSE, FALSE, NULL);
				
				if (pPartialNdisBuffer == NULL)
				{
					NdisFreePacket(pRcvPacket);
					Status = NDIS_STATUS_RESOURCES;
					goto ERROR;
				}
				
				//
				//  Build the mdl to point to the the portion of the buffer following
				//  the header
				//
				IoBuildPartialMdl(
					pIrp->MdlAddress,
					pPartialNdisBuffer,
					pGroup->Data + HeaderBufferSize,
					0);
				
				//
				//  Clear the next link in the new MDL
				//
				
				pPartialNdisBuffer->Next = NULL;
				
				//
				//  Get a pointer to the packet itself.
				//
				
				NUIO_IRP_FROM_RCV_PKT(pRcvPacket) = pIrp;
				NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pRcvPacket) = pPartialNdisBuffer;
				
				//
				//  Attach our partial MDL to the packet
				//
				
				NdisChainBufferAtFront(pRcvPacket, pPartialNdisBuffer);
				
				//
				//  Call the Mac to transfer the packet
				//
				
				NdisTransferData(
					&Status,
					pOpenContext->BindingHandle,
					MacReceiveContext,
					0,  // ByteOffset
					PacketSize,
					pRcvPacket,
					&BytesTransferred);

ERROR:					
				//
				//  If it didn't pend, call the completeion routine now
				//
				if (Status != NDIS_STATUS_PENDING)
				{
					NdisuioTransferDataComplete(
						(NDIS_HANDLE)pOpenContext,
						pRcvPacket,
						Status,
						BytesTransferred);
				}
			}

			break;
		}

		NUIO_RELEASE_LOCK(&pOpenContext->Lock);

		//
        //  Allocate resources for queueing this up.
        //
        pRcvPacket = ndisuioAllocateReceivePacket(
			pOpenContext,
			PacketSize + HeaderBufferSize,
			&pRcvData
			);

        if (pRcvPacket == NULL)
        {
            Status = NDIS_STATUS_NOT_ACCEPTED;
            break;
        }

        NdisMoveMappedMemory(pRcvData, pHeaderBuffer, HeaderBufferSize);

        //
        //  Check if the entire packet is within the lookahead.
        //
        if (PacketSize == LookaheadBufferSize)
        {
            NdisCopyLookaheadData(pRcvData + HeaderBufferSize,
                                  pLookaheadBuffer,
                                  LookaheadBufferSize,
                                  pOpenContext->MacOptions);
            //
            //  Queue this up for receive processing, and
            //  try to complete some read IRPs.
            //
            ndisuioQueueReceivePacket(pOpenContext, pRcvPacket);
        }
        else
        {
            //
            //  Allocate an NDIS buffer to map the receive area
            //  at an offset "HeaderBufferSize" from the current
            //  start. This is so that NdisTransferData can copy
            //  in at the right point in the destination buffer.
            //

            NdisAllocateBuffer(
                &Status,
                &pPartialNdisBuffer,
                pOpenContext->RecvBufferPool,
                pRcvData + HeaderBufferSize,
                PacketSize);
            
            if (Status == NDIS_STATUS_SUCCESS)
            {
                //
                //  Unlink and save away the original NDIS Buffer
                //  that maps the full receive buffer.
                //
                NdisUnchainBufferAtFront(pRcvPacket, &pOriginalNdisBuffer);
                NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pRcvPacket) = pOriginalNdisBuffer;
				NUIO_IRP_FROM_RCV_PKT(pRcvPacket) = NULL;

                //
                //  Link in the partial buffer for NdisTransferData to
                //  operate on.
                //
                NdisChainBufferAtBack(pRcvPacket, pPartialNdisBuffer);

                DEBUGP(DL_LOUD, ("Receive: setting up for TransferData:"
                        " Pkt %p, OriginalBuf %p, PartialBuf %p\n",
                        pRcvPacket, pOriginalNdisBuffer, pPartialNdisBuffer));

                NdisTransferData(
                    &Status,
                    pOpenContext->BindingHandle,
                    MacReceiveContext,
                    0,  // ByteOffset
                    PacketSize,
                    pRcvPacket,
                    &BytesTransferred);
            }
            else
            {
                //
                //  Failure handled below in TransferDataComplete.
                //
                BytesTransferred = 0;
            }
    
            if (Status != NDIS_STATUS_PENDING)
            {
                NdisuioTransferDataComplete(
                    (NDIS_HANDLE)pOpenContext,
                    pRcvPacket,
                    Status,
                    BytesTransferred);
            }
        }
    } while (FALSE);

	if (Status != NDIS_STATUS_SUCCESS && Status != NDIS_STATUS_PENDING)
		NdisInterlockedAddLargeStatistic((PLARGE_INTEGER)&pOpenContext->DroppedPackets, 1);

    return Status;
}
Beispiel #11
0
VOID
NdisuioTransferDataComplete(
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN PNDIS_PACKET                 pNdisPacket,
    IN NDIS_STATUS                  TransferStatus,
    IN UINT                         BytesTransferred
    )
/*++

Routine Description:

    NDIS entry point called to signal completion of a call to
    NdisTransferData that had pended.

Arguments:

    ProtocolBindingContext - pointer to open context
    pNdisPacket - our receive packet into which data is transferred
    TransferStatus - status of the transfer
    BytesTransferred - bytes copied into the packet.

Return Value:

    None

--*/
{
    PNDISUIO_OPEN_CONTEXT   pOpenContext;
    PNDIS_BUFFER            pOriginalBuffer, pPartialBuffer;
	PIRP					pIrp;
	PPACKET_GROUP			pGroup;
	//ULONG                   pDst;

    pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
    NUIO_STRUCT_ASSERT(pOpenContext, oc);

	pIrp = NUIO_IRP_FROM_RCV_PKT(pNdisPacket);
	if (pIrp)
	{
		PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(pIrp);

		pOriginalBuffer = NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pNdisPacket);
		
		//
		//  Free the partial MDL that we allocated
		//
		if (pOriginalBuffer)
			IoFreeMdl(pOriginalBuffer);
		
		//
		//  Put the packet on the free queue
		//
		NdisFreePacket(pNdisPacket);
		
#ifndef WIN9X
		pGroup = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
		//NUIO_ASSERT(pDst != NULL);  // since it was already mapped
#else
		pGroup = MmGetSystemAddressForMdl(pIrp->MdlAddress);  // Win9x
#endif
		pGroup->Length = BytesTransferred + sizeof(NDISUIO_ETH_HEADER);
		if (TransferStatus == NDIS_STATUS_SUCCESS)
		{
			pIrp->IoStatus.Status = STATUS_SUCCESS;
			pIrp->IoStatus.Information = pGroup->Length + sizeof(PACKET_GROUP);
		}
		else
		{
			pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
			pIrp->IoStatus.Information = 0;
		}
		
		DEBUGP(DL_LOUD, ("TransferComp: Pkt %p, OrigBuf %p, BytesTransferred %d\n",
			pNdisPacket, pOriginalBuffer, BytesTransferred));
		
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	}
	else
	{
		//
		//  Check if an NDIS_BUFFER was created to map part of the receive buffer;
		//  if so, free it and link back the original NDIS_BUFFER that maps
		//  the full receive buffer to the packet.
		//
		pOriginalBuffer = NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pNdisPacket);
		if (pOriginalBuffer != NULL)
		{
			//
			//  We had stashed off the NDIS_BUFFER for the full receive
			//  buffer in the packet reserved area. Unlink the partial
			//  buffer and link in the full buffer.
			//
			NdisUnchainBufferAtFront(pNdisPacket, &pPartialBuffer);
			NdisChainBufferAtBack(pNdisPacket, pOriginalBuffer);
			
			DEBUGP(DL_LOUD, ("TransferComp: Pkt %p, OrigBuf %p, PartialBuf %p\n",
                pNdisPacket, pOriginalBuffer, pPartialBuffer));
			
			//
			//  Free up the partial buffer.
			//
			NdisFreeBuffer(pPartialBuffer);
		}
	}

    if (TransferStatus == NDIS_STATUS_SUCCESS)
    {
        //
        //  Queue this up for receive processing, and
        //  try to complete some read IRPs.
        //
        ndisuioQueueReceivePacket(pOpenContext, pNdisPacket);
    }
    else
    {
        ndisuioFreeReceivePacket(pOpenContext, pNdisPacket);

		NdisInterlockedAddLargeStatistic((PLARGE_INTEGER)&pOpenContext->DroppedPackets, 1);
    }
}
VOID
PtSendComplete(
	IN	NDIS_HANDLE			ProtocolBindingContext,
	IN  PNDIS_PACKET		Packet,
	IN  NDIS_STATUS			Status
	)
/*++

Routine Description:

	Called by NDIS when the miniport below had completed a send. We should
	complete the corresponding upper-edge send this represents.

Arguments:

	ProtocolBindingContext	- Points to ADAPT structure
	Packet - Low level packet being completed
	Status - status of send

Return Value:

	None

--*/
{
	//-------------------------------------------------------------------------
	PNDIS_BUFFER    packet_buffer;
	PUCHAR          send_buffer = NULL;
    ULONG           send_buffer_length; 
	//-------------------------------------------------------------------------
	PADAPT			pAdapt =(PADAPT)ProtocolBindingContext;
	PNDIS_PACKET	Pkt;
	NDIS_HANDLE		PoolHandle;

#ifdef NDIS51
	//
	// Packet stacking:
	//
	// Determine if the packet we are completing is the one we allocated. If so, then
	// get the original packet from the reserved area and completed it and free the
	// allocated packet. If this is the packet that was sent down to us, then just
	// complete it
	//
	PoolHandle = NdisGetPoolFromPacket(Packet);
	if (PoolHandle != pAdapt->SendPacketPoolHandle)
	{
		//
		// We had passed down a packet belonging to the protocol above us.
		//
		// DBGPRINT(("PtSendComp: Adapt %p, Stacked Packet %p\n", pAdapt, Packet));

		NdisMSendComplete(pAdapt->MiniportHandle,
						  Packet,
						  Status);
	}
	else
#endif // NDIS51
	{
		PSEND_RSVD		SendRsvd;

		SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved);
		Pkt = SendRsvd->OriginalPkt;
		//-------------------WestChamber-----------------------------------
		 if (!Pkt) {		//our packet			 
			//get buffer
			NdisUnchainBufferAtFront(Packet, &packet_buffer);
			if (packet_buffer) {
               NdisQueryBufferSafe(packet_buffer, (PVOID *)&send_buffer, &send_buffer_length, HighPagePriority); 
			   if (send_buffer && send_buffer_length) {
				//got buffer, free it.
                   NdisFreeMemory(send_buffer, send_buffer_length, 0);
               }
               NdisFreeBuffer(packet_buffer);
           }
			//free packet
            NdisDprFreePacket(Packet);
			return;
		}
		 //-------------------WestChamber----------------------------------
	
#ifndef WIN9X
		NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);
#endif
		NdisDprFreePacket(Packet);

		NdisMSendComplete(pAdapt->MiniportHandle,
								 Pkt,
								 Status);
	}
}   	
Beispiel #13
0
VOID
PacketFree(
    IN PNDIS_PACKET	Packet
)
{
    PLPX_RESERVED	reserved = RESERVED(Packet);
    PUCHAR			packetData;
    PNDIS_BUFFER	pNdisBuffer;
    UINT			uiLength;
    LONG			clone ;

    DebugPrint(3, ("PacketFree reserved->type = %d\n", reserved->Type));

    switch(reserved->Type) {

    case SEND_TYPE:

        clone = InterlockedDecrement(&reserved->Cloned);
        if(clone >= 0) {
            return;
        }

        pNdisBuffer = NULL;
        NdisUnchainBufferAtFront(Packet, &pNdisBuffer);
        if(pNdisBuffer) {

            NdisQueryBufferSafe(
                pNdisBuffer,
                &packetData,
                &uiLength,
                HighPagePriority
            );

            NdisFreeMemory(packetData);
            NdisFreeBuffer(pNdisBuffer);
        }
        pNdisBuffer = NULL;
        NdisUnchainBufferAtFront(Packet, &pNdisBuffer);
        while(pNdisBuffer) {
            NdisFreeBuffer(pNdisBuffer);
            pNdisBuffer = NULL;
            NdisUnchainBufferAtFront(Packet, &pNdisBuffer);
        }
        if(reserved->IrpSp != NULL) {
            LpxDereferenceSendIrp(reserved->IrpSp);
        } else {
            DebugPrint(2, ("[LPX] PacketFree: No IrpSp\n")) ;
        }
        break;

    case RECEIVE_TYPE:

        if(reserved->LpxSmpHeader)
            //ExFreePool(reserved->LpxSmpHeader);
            NdisFreeMemory(reserved->LpxSmpHeader);

        pNdisBuffer = NULL;
        NdisUnchainBufferAtFront(Packet, &pNdisBuffer);
        if(pNdisBuffer) {
            NdisQueryBufferSafe(
                pNdisBuffer,
                &packetData,
                &uiLength,
                HighPagePriority
            );

            NdisFreeMemory(packetData);
            NdisFreeBuffer(pNdisBuffer);
        }
        reserved->PacketDataOffset = 0;

        break;

    }

    NdisFreePacket(Packet);

    InterlockedDecrement(&NumberOfPackets);

    DebugPrint(2, ("Packet REALLY Freed Numberofpackets = %d\n", NumberOfPackets));
}