Beispiel #1
0
VOID
DeferredRxCompleteDpc(
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
){
	PRX_COMP_DPC_CTX     rxCompCtx = DeferredContext;
	PDEVICE_CONTEXT		deviceContext = rxCompCtx->DeviceContext;

	UNREFERENCED_PARAMETER(Dpc);
	UNREFERENCED_PARAMETER(SystemArgument1);
	UNREFERENCED_PARAMETER(SystemArgument2);

	LpxReceiveComplete2(deviceContext, &rxCompCtx->ReceivedPackets);

	ExFreeToNPagedLookasideList(&deviceContext->DeferredRxCompContext, rxCompCtx);

	ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
	ClearFlag( deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_DEFFERED_DPC_SET );
	RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );

	LpxReceiveComplete( deviceContext );

	LpxDereferenceDeviceContext("RxCompDpc", deviceContext, DCREF_REQUEST);
}
Beispiel #2
0
PCONNECTION
WalkConnectionTable (
    IN PENDPOINT Endpoint,
    IN OUT PCSHORT Index
    )
{
    CSHORT i;
    PTABLE_HEADER tableHeader;
    PCONNECTION connection;
    KIRQL oldIrql;

    ACQUIRE_SPIN_LOCK( &ENDPOINT_SPIN_LOCK(0), &oldIrql );
    for ( i = 1; i < ENDPOINT_LOCK_COUNT ; i++ ) {
        ACQUIRE_DPC_SPIN_LOCK( &ENDPOINT_SPIN_LOCK(i) );
    }

    tableHeader = &Endpoint->ConnectionTable;

    for ( i = *Index + 1; i < tableHeader->TableSize; i++ ) {

        connection = (PCONNECTION)tableHeader->Table[i].Owner;
        if ( (connection != NULL) &&
             (GET_BLOCK_STATE(connection) == BlockStateActive) ) {
            *Index = i;
            SrvReferenceConnectionLocked( connection );
            goto exit;
        }
    }
    connection = NULL;

exit:

    for ( i = ENDPOINT_LOCK_COUNT-1 ; i > 0  ; i-- ) {
        RELEASE_DPC_SPIN_LOCK( &ENDPOINT_SPIN_LOCK(i) );
    }
    RELEASE_SPIN_LOCK( &ENDPOINT_SPIN_LOCK(0), oldIrql );

    return connection;
} // WalkConnectionTable
Beispiel #3
0
VOID
DeferredLpxReceiveComplete (
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
	)
{
	PDEVICE_CONTEXT		deviceContext = DeferredContext;

	UNREFERENCED_PARAMETER( Dpc );
	UNREFERENCED_PARAMETER( SystemArgument1 );
	UNREFERENCED_PARAMETER( SystemArgument2 );

	LpxReceiveComplete2( deviceContext, &deviceContext->DeferredLpxReceiveCompleteDpcPacketList );

	ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
	deviceContext->DeferredLpxReceiveCompleteDpcRun = FALSE;
	RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );

	LpxReceiveComplete( deviceContext );

	LpxDereferenceDeviceContext( "DeferredLpxReceiveComplete", deviceContext, DCREF_REQUEST );
}
Beispiel #4
0
VOID
LpxReceiveComplete (
	IN NDIS_HANDLE BindingContext
	)
{
#if 1

	PDEVICE_CONTEXT		deviceContext = (PDEVICE_CONTEXT)BindingContext;
	BOOLEAN				queued;


	ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );

	IF_LPXDBG(LPX_DEBUG_TEST)
		ASSERT( FALSE );

	if (IsListEmpty(&deviceContext->PacketInProgressList)) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
		return;
	}

	if (deviceContext->DeferredLpxReceiveCompleteDpcRun == TRUE) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
		return;
	}

	LPX_ASSERT( IsListEmpty(&deviceContext->DeferredLpxReceiveCompleteDpcPacketList) );

	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Flink = deviceContext->PacketInProgressList.Flink;
	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Blink = deviceContext->PacketInProgressList.Blink;
	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Flink->Blink = &deviceContext->DeferredLpxReceiveCompleteDpcPacketList;
	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Blink->Flink = &deviceContext->DeferredLpxReceiveCompleteDpcPacketList;

	InitializeListHead( &deviceContext->PacketInProgressList );

	//
	// Perform actual LPX receive completion
	// If the completion is deferred, queue the DPC.
	// Some NIC drivers show receiving performance degrade
	// when receive complete routine consumes much CPU time.
	// Ex> Broadcom Giga ehternet 3788. driver name = b57nd60x.sys 11/1/2005/11:30 164KB
	//

	LpxReferenceDeviceContext( "LpxReceiveComplete", deviceContext, DCREF_REQUEST );

	deviceContext->DeferredLpxReceiveCompleteDpcRun = TRUE;

	queued = KeInsertQueueDpc( &deviceContext->DeferredLpxReceiveCompleteDpc, NULL, NULL );
	
	if (queued) {

	} else {

		LPX_ASSERT( FALSE );
		deviceContext->DeferredLpxReceiveCompleteDpcRun = FALSE;
		LpxDereferenceDeviceContext( "LpxReceiveComplete", deviceContext, DCREF_REQUEST );		
	}

	if (queued == FALSE) {

		deviceContext->DeferredLpxReceiveCompleteDpcRun = TRUE;
	}

	RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );

	if (queued == FALSE) {

		LpxReceiveComplete2( BindingContext, &deviceContext->DeferredLpxReceiveCompleteDpcPacketList );

		ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
		deviceContext->DeferredLpxReceiveCompleteDpcRun = FALSE;
		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
	}

#else

	PDEVICE_CONTEXT		deviceContext = (PDEVICE_CONTEXT)BindingContext;
	PRX_COMP_DPC_CTX	rxCompDpcCtx;
	LIST_ENTRY			receivedPackets;

	ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);

	IF_LPXDBG(LPX_DEBUG_TEST)
		ASSERT( FALSE );

	if (FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_DEFFERED_DPC_SET)) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);
		return;
	}

	if (deviceContext->SendingThreadCount) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);
		return;
	}

	if (IsListEmpty(&deviceContext->PacketInProgressList)) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);
		return;
	}

	//
	// Allocate a DPC context
	//
	rxCompDpcCtx = ExAllocateFromNPagedLookasideList(&deviceContext->DeferredRxCompContext);
	
	if (rxCompDpcCtx == NULL) {

		LPX_ASSERT( FALSE );
		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);
		return;
	}

	//
	// Move received packets from the in-progress list to the temporary list.
	// LpxReceiveComplete2() will process only packets in this temporary list.
	// By doing this, we can spread out time-consume in LpxReceiveComplete2().
	// Especially, deferred LpxReceiveComplete2() in DPC routine does not
	// need to loop and timeout-check because LpxReceiveComplete2() will process
	// only packets in the temporary list.
	//
	if(rxCompDpcCtx) {
		KeInitializeDpc(&rxCompDpcCtx->Dpc, DeferredRxCompleteDpc, rxCompDpcCtx);
		rxCompDpcCtx->DeviceContext = deviceContext;
		rxCompDpcCtx->ReceivedPackets.Flink = deviceContext->PacketInProgressList.Flink;
		rxCompDpcCtx->ReceivedPackets.Blink = deviceContext->PacketInProgressList.Blink;
		deviceContext->PacketInProgressList.Flink->Blink = &rxCompDpcCtx->ReceivedPackets;
		deviceContext->PacketInProgressList.Blink->Flink = &rxCompDpcCtx->ReceivedPackets;
	} else {
		receivedPackets.Flink = deviceContext->PacketInProgressList.Flink;
		receivedPackets.Blink = deviceContext->PacketInProgressList.Blink;
		deviceContext->PacketInProgressList.Flink->Blink = &receivedPackets;
		deviceContext->PacketInProgressList.Blink->Flink = &receivedPackets;
	}
	InitializeListHead(&deviceContext->PacketInProgressList);

	//
	// Perform actual LPX receive completion
	// If the completion is deferred, queue the DPC.
	// Some NIC drivers show receiving performance degrade
	// when receive complete routine consumes much CPU time.
	// Ex> Broadcom Giga ehternet 3788. driver name = b57nd60x.sys 11/1/2005/11:30 164KB
	//

	if(rxCompDpcCtx) {
		BOOLEAN	queued;
		LpxReferenceDeviceContext("RxCompDpc", deviceContext, DCREF_REQUEST);
		queued = KeInsertQueueDpc(&rxCompDpcCtx->Dpc, NULL, NULL);
		ASSERT(queued);
		if(!queued) {
			LpxDereferenceDeviceContext("RxCompDpc", deviceContext, DCREF_REQUEST);
		
		} else {

			SetFlag( deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_DEFFERED_DPC_SET );
		}

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);

	} else {
	
		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);

		// Call actual LPX receive completion directly.
		LpxReceiveComplete2( BindingContext, &receivedPackets );
	}

#endif
}
Beispiel #5
0
NDIS_STATUS
LpxReceiveIndication (
	IN NDIS_HANDLE	ProtocolBindingContext,
	IN NDIS_HANDLE	MacReceiveContext,
	IN PVOID		HeaderBuffer,
	IN UINT		    HeaderBufferSize,
	IN PVOID		LookAheadBuffer,
	IN UINT		    LookAheadBufferSize,
	IN UINT		    PacketSize
	)
/*++

Routine Description:

	This routine receives control from the physical provider as an
	indication that a frame has been received on the physical link.
	This routine is time critical, so we only allocate a
	buffer and copy the packet into it. We also perform minimal
	validation on this packet. It gets queued to the device context
	to allow for processing later.

Arguments:

	BindingContext - The Adapter Binding specified at initialization time.

	ReceiveContext - A magic cookie for the MAC.

	HeaderBuffer - pointer to a buffer containing the packet header.

	HeaderBufferSize - the size of the header.

	LookaheadBuffer - pointer to a buffer containing the negotiated minimum
		amount of buffer I get to look at (not including header).

	LookaheadBufferSize - the size of the above. May be less than asked
		for, if that's all there is.

	PacketSize - Overall size of the packet (not including header).

Return Value:

	NDIS_STATUS - status of operation, one of:

			     NDIS_STATUS_SUCCESS if packet accepted,
			     NDIS_STATUS_NOT_RECOGNIZED if not recognized by protocol,
			     NDIS_any_other_thing if I understand, but can't handle.

--*/
{
	PDEVICE_CONTEXT	deviceContext;
	USHORT		    protocol;
	PNDIS_PACKET	packet;
	NDIS_STATUS		status;
	UINT		    bytesTransfered = 0;
	UINT		    startOffset = 0;


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

	//
	//	validation
	//

	if (HeaderBufferSize != ETHERNET_HEADER_LENGTH) {

		DebugPrint( 4, ("HeaderBufferSize = %x\n", HeaderBufferSize) );
		return NDIS_STATUS_NOT_ACCEPTED;
	}
	
	RtlCopyMemory( (PUCHAR)&protocol, &((PUCHAR)HeaderBuffer)[12], sizeof(USHORT) );

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

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

#ifdef __LPX__
		NdisCopyLookaheadData( (PUCHAR)&protocol,
								&((PUCHAR)LookAheadBuffer)[LENGTH_8022LLCSNAP - 2],
								sizeof(USHORT),
								deviceContext->MacOptions );
#endif
		PacketSize -= LENGTH_8022LLCSNAP;
		LookAheadBufferSize -= LENGTH_8022LLCSNAP;
		startOffset = LENGTH_8022LLCSNAP;
	}

	if (protocol != HTONS(ETH_P_LPX)) {
	
		DebugPrint( 4, ("Type = %x\n", protocol) );
		return NDIS_STATUS_NOT_ACCEPTED;
	}


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

	//ACQUIRE_DPC_SPIN_LOCK( &deviceContext->SpinLock );

	if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) {
	
		//RELEASE_DPC_SPIN_LOCK( &deviceContext->SpinLock );
		DebugPrint( 4,("Device is not initialized. Drop packet\n") );

		return NDIS_STATUS_NOT_ACCEPTED;
	}

	ASSERT( deviceContext->NdisBindingHandle );

	//RELEASE_DPC_SPIN_LOCK( &deviceContext->SpinLock );

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

#if 1 //DBG // Enabled for testing

	if (PacketRxDropRate) {

		PacketRxCountForDrop++;
				
		if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) {
			PLPX_HEADER        lpxHeader = (PLPX_HEADER)LookAheadBuffer;
#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") );

			return NDIS_STATUS_NOT_ACCEPTED;
		}
	}

#endif

	ASSERT( startOffset == 0 );

	DebugPrint( 4, ("LpxReceiveIndication, PacketSize = %d, LookAheadBufferSize = %d, LPX_HEADER size = %d\n",
					 PacketSize, LookAheadBufferSize, sizeof(LPX_HEADER)) );

	if (LookAheadBufferSize - startOffset >= sizeof(LPX_HEADER)) {

		PNDIS_BUFFER	firstBuffer;    
		PUCHAR		    packetData;
		PLPX_HEADER		lpxHeader;
		USHORT			lpxHeaderSize;

		
		lpxHeader = (PLPX_HEADER)((PBYTE)LookAheadBuffer + startOffset);
		
		lpxHeaderSize = sizeof(LPX_HEADER);
	
		if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) {

			lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
		}

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

			lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
		}

		if (NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) == lpxHeaderSize) {

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

			if (status == STATUS_SUCCESS) {

				NdisCopyLookaheadData( &RESERVED(packet)->EthernetHeader,
										HeaderBuffer,
										ETHERNET_HEADER_LENGTH,
										deviceContext->MacOptions );

				RESERVED(packet)->EthernetHeader.Type = protocol;
				RESERVED(packet)->RecvTime = CurrentTime();
			
				RtlCopyMemory( &RESERVED(packet)->LpxHeader, lpxHeader, lpxHeaderSize );
				RESERVED(packet)->HeaderCopied = TRUE;

				RESERVED(packet)->PacketRawDataLength = 0;
				RESERVED(packet)->PacketRawDataOffset = 0;

				LpxTransferDataComplete( deviceContext,
					                     packet,
					                     NDIS_STATUS_SUCCESS,
					                     LookAheadBufferSize );

				return NDIS_STATUS_SUCCESS;
			}

		} else if (LookAheadBufferSize - startOffset >= NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK)) {
				
			status = RcvPacketAlloc( deviceContext,
									 NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize,
									 &packet );

			if (status == STATUS_SUCCESS) {
			
				NdisCopyLookaheadData( &RESERVED(packet)->EthernetHeader,
										HeaderBuffer,
										ETHERNET_HEADER_LENGTH,
										deviceContext->MacOptions );

				RESERVED(packet)->EthernetHeader.Type = protocol;
				RESERVED(packet)->RecvTime = CurrentTime();

				RtlCopyMemory( &RESERVED(packet)->LpxHeader, lpxHeader, lpxHeaderSize );
				RESERVED(packet)->HeaderCopied = TRUE;

				RESERVED(packet)->PacketRawDataLength = NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize;
				RESERVED(packet)->PacketRawDataOffset = 0;

				NdisQueryPacket( packet, NULL, NULL, &firstBuffer, NULL );
				packetData = MmGetMdlVirtualAddress( firstBuffer );

				NdisCopyLookaheadData( packetData,
									   (PBYTE)LookAheadBuffer + startOffset + lpxHeaderSize,
									   RESERVED(packet)->PacketRawDataLength,
									   deviceContext->MacOptions );

				LpxTransferDataComplete( deviceContext,
					                     packet,
					                     NDIS_STATUS_SUCCESS,
					                     LookAheadBufferSize );

				return NDIS_STATUS_SUCCESS;
			}

		} else {

			status = RcvPacketAlloc( deviceContext,
									 startOffset + NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK),
									 &packet );
			
			if (status == STATUS_SUCCESS) {
			
				NdisCopyLookaheadData( &RESERVED(packet)->EthernetHeader,
										HeaderBuffer,
										ETHERNET_HEADER_LENGTH,
										deviceContext->MacOptions );

				RESERVED(packet)->EthernetHeader.Type = protocol;
				RESERVED(packet)->RecvTime = CurrentTime();

				RtlCopyMemory( &RESERVED(packet)->LpxHeader, lpxHeader, lpxHeaderSize );
				RESERVED(packet)->HeaderCopied = TRUE;

				RESERVED(packet)->PacketRawDataLength = startOffset + NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK);
				RESERVED(packet)->PacketRawDataOffset = startOffset + lpxHeaderSize;
			}
		}

	} else {

		PLPX_HEADER		lpxHeader;
		PNDIS_BUFFER	firstBuffer;	
		PUCHAR			packetData;
		UINT			packetDataLength;

		ASSERT( FALSE );

		status = RcvPacketAlloc( deviceContext, PacketSize, &packet );
		
		if (status == STATUS_SUCCESS) {
		
			RtlCopyMemory( &RESERVED(packet)->EthernetHeader,
						   HeaderBuffer,
						   ETHERNET_HEADER_LENGTH );

			RESERVED(packet)->EthernetHeader.Type = protocol;
			RESERVED(packet)->RecvTime = CurrentTime();

			RESERVED(packet)->PacketRawDataLength = PacketSize;
			RESERVED(packet)->PacketRawDataOffset = startOffset;

			NdisQueryPacket( packet, NULL, NULL, &firstBuffer, NULL );
			NdisQueryBufferSafe( firstBuffer, &packetData, &packetDataLength, HighPagePriority );

			lpxHeader = (PLPX_HEADER)(packetData + RESERVED(packet)->PacketRawDataOffset);
			RtlZeroMemory( lpxHeader, sizeof(LPX_HEADER) );

			RESERVED(packet)->HeaderCopied = FALSE;
		}
	}

	if (status != NDIS_STATUS_SUCCESS) {
	
		return NDIS_STATUS_NOT_ACCEPTED;
	}

	ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS );
			
	if (deviceContext->NdisBindingHandle) {

		//ASSERT( FALSE );

		NdisTransferData( &status,
						  deviceContext->NdisBindingHandle,
						  MacReceiveContext,
						  0, //RESERVED(packet)->PacketRawDataOffset,
						  RESERVED(packet)->PacketRawDataLength,
						  packet,
						  &bytesTransfered );

			
		if (status == NDIS_STATUS_PENDING) {

		    status = NDIS_STATUS_SUCCESS;
		
		} else if (status == NDIS_STATUS_SUCCESS) {
		
			LpxTransferDataComplete( deviceContext,
									 packet,
									 status,
									 bytesTransfered );
			
		} else {
	
			ASSERT( FALSE );
			status = NDIS_STATUS_NOT_ACCEPTED;
			DebugPrint( 1, ("NdisTransferData() failed. STATUS=%08lx\n", status) );
		}

	} else {
			
		RELEASE_DPC_SPIN_LOCK( &deviceContext->SpinLock );
		status = NDIS_STATUS_NOT_ACCEPTED;
		DebugPrint( 1, ("Invalid device status. STATUS=%08lx\n", status) );
	}

	return status;
}
Beispiel #6
0
NTSTATUS
NbfTdiReceive(
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the TdiReceive request for the transport provider.

Arguments:

    Irp - I/O Request Packet for this request.

Return Value:

    NTSTATUS - status of operation.

--*/

{
    NTSTATUS status;
    PTP_CONNECTION connection;
    KIRQL oldirql;
    PIO_STACK_LOCATION irpSp;

    //
    // verify that the operation is taking place on a connection. At the same
    // time we do this, we reference the connection. This ensures it does not
    // get removed out from under us. Note also that we do the connection
    // lookup within a try/except clause, thus protecting ourselves against
    // really bogus handles
    //

    irpSp = IoGetCurrentIrpStackLocation (Irp);
    connection = irpSp->FileObject->FsContext;

    //
    // Check that this is really a connection.
    //

    if ((connection->Size != sizeof (TP_CONNECTION)) ||
        (connection->Type != NBF_CONNECTION_SIGNATURE)) {
#if DBG
        NbfPrint2 ("TdiReceive: Invalid Connection %lx Irp %lx\n", connection, Irp);
#endif
        return STATUS_INVALID_CONNECTION;
    }

    //
    // Initialize bytes transferred here.
    //

    Irp->IoStatus.Information = 0;              // reset byte transfer count.

    // This reference is removed by NbfDestroyRequest.

    KeRaiseIrql (DISPATCH_LEVEL, &oldirql);

    ACQUIRE_DPC_C_SPIN_LOCK (&connection->SpinLock);

    if ((connection->Flags & CONNECTION_FLAGS_READY) == 0) {

        RELEASE_DPC_C_SPIN_LOCK (&connection->SpinLock);

        Irp->IoStatus.Status = connection->Status;
        IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);

        status = STATUS_PENDING;

    } else {
        KIRQL cancelIrql;

        //
        // Once the reference is in, LinkSpinLock will be valid.
        //

        NbfReferenceConnection("TdiReceive request", connection, CREF_RECEIVE_IRP);
        RELEASE_DPC_C_SPIN_LOCK (&connection->SpinLock);

        IoAcquireCancelSpinLock(&cancelIrql);
        ACQUIRE_DPC_SPIN_LOCK (connection->LinkSpinLock);

        IRP_RECEIVE_IRP(irpSp) = Irp;
        IRP_RECEIVE_REFCOUNT(irpSp) = 1;

#if DBG
        NbfReceives[NbfReceivesNext].Irp = Irp;
        NbfReceives[NbfReceivesNext].Request = NULL;
        NbfReceives[NbfReceivesNext].Connection = (PVOID)connection;
        NbfReceivesNext = (NbfReceivesNext++) % TRACK_TDI_LIMIT;
#endif

        //
        // If this IRP has been cancelled, complete it now.
        //

        if (Irp->Cancel) {

#if DBG
            NbfCompletedReceives[NbfCompletedReceivesNext].Irp = Irp;
            NbfCompletedReceives[NbfCompletedReceivesNext].Request = NULL;
            NbfCompletedReceives[NbfCompletedReceivesNext].Status = STATUS_CANCELLED;
            {
                ULONG i,j,k;
                PUCHAR va;
                PMDL mdl;

                mdl = Irp->MdlAddress;

                NbfCompletedReceives[NbfCompletedReceivesNext].Contents[0] = (UCHAR)0;

                i = 1;
                while (i<TRACK_TDI_CAPTURE) {
                    if (mdl == NULL) break;
                    va = MmGetSystemAddressForMdl (mdl);
                    j = MmGetMdlByteCount (mdl);

                    for (i=i,k=0;i<TRACK_TDI_CAPTURE&k<j;i++,k++) {
                        NbfCompletedReceives[NbfCompletedReceivesNext].Contents[i] = *va++;
                    }
                    mdl = mdl->Next;
                }
            }

            NbfCompletedReceivesNext = (NbfCompletedReceivesNext++) % TRACK_TDI_LIMIT;
#endif

            //
            // It is safe to do this with locks held.
            //
            NbfCompleteReceiveIrp (Irp, STATUS_CANCELLED, 0);

            RELEASE_DPC_SPIN_LOCK (connection->LinkSpinLock);
            IoReleaseCancelSpinLock(cancelIrql);

        } else {

            //
            // Insert onto the receive queue, and make the IRP
            // cancellable.
            //

            InsertTailList (&connection->ReceiveQueue,&Irp->Tail.Overlay.ListEntry);
            IoSetCancelRoutine(Irp, NbfCancelReceive);

            //
            // Release the cancel spinlock out of order. Since we were
            // already at dpc level when it was acquired, we don't
            // need to swap irqls.
            //
            ASSERT(cancelIrql == DISPATCH_LEVEL);
            IoReleaseCancelSpinLock(cancelIrql);

            //
            // This call releases the link spinlock, and references the
            // connection first if it needs to access it after
            // releasing the lock.
            //

            AwakenReceive (connection);             // awaken if sleeping.

        }

        status = STATUS_PENDING;

    }

    KeLowerIrql (oldirql);

    return status;
} /* TdiReceive */
Beispiel #7
0
VOID
ActivateReceive(
    PTP_CONNECTION Connection
    )

/*++

Routine Description:

    This routine activates the next TdiReceive request on the specified
    connection object if there is no active request on that connection
    already.  This allows the request to accept data on the connection.

    NOTE: THIS FUNCTION MUST BE CALLED AT DPC LEVEL.

Arguments:

    Connection - Pointer to a TP_CONNECTION object.

Return Value:

    none.

--*/

{
    PIRP Irp;

    ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL);

    IF_NBFDBG (NBF_DEBUG_RCVENG) {
        NbfPrint0 ("    ActivateReceive:  Entered.\n");
    }

    //
    // The ACTIVE_RECEIVE bitflag will be set on the connection if
    // the receive-fields in the CONNECTION object are valid.  If
    // this flag is cleared, then we try to make the next TdiReceive
    // request in the ReceiveQueue the active request.
    //

    ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
    if (!(Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE)) {
        if (!IsListEmpty (&Connection->ReceiveQueue)) {

            //
            // Found a receive, so make it the active one.
            //

            Connection->Flags |= CONNECTION_FLAGS_ACTIVE_RECEIVE;

            Irp = CONTAINING_RECORD(
                      Connection->ReceiveQueue.Flink,
                      IRP,
                      Tail.Overlay.ListEntry);
            Connection->MessageBytesReceived = 0;
            Connection->MessageBytesAcked = 0;
            Connection->MessageInitAccepted = 0;
            Connection->CurrentReceiveIrp = Irp;
            Connection->CurrentReceiveSynchronous =
                Connection->Provider->MacInfo.SingleReceive;
            Connection->CurrentReceiveMdl = Irp->MdlAddress;
            Connection->ReceiveLength = IRP_RECEIVE_LENGTH(IoGetCurrentIrpStackLocation(Irp));
            Connection->ReceiveByteOffset = 0;
        }
    }
    RELEASE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
    IF_NBFDBG (NBF_DEBUG_RCVENG) {
        NbfPrint0 ("    ActivateReceive:  Exiting.\n");
    }
} /* ActivateReceive */
Beispiel #8
0
VOID
LpxReceiveComplete (
	IN NDIS_HANDLE BindingContext
	)
{
	PDEVICE_CONTEXT deviceContext = (PDEVICE_CONTEXT)BindingContext;
	BOOLEAN			queued;


	ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );

	IF_LPXDBG (LPX_DEBUG_TEST) {

		NDAS_ASSERT(FALSE);
	}

	if (IsListEmpty(&deviceContext->PacketInProgressList)) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
		return;
	}

	if (deviceContext->DeferredLpxReceiveCompleteDpcRun == TRUE) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
		return;
	}

	NDAS_ASSERT( IsListEmpty(&deviceContext->DeferredLpxReceiveCompleteDpcPacketList) );

	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Flink = deviceContext->PacketInProgressList.Flink;
	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Blink = deviceContext->PacketInProgressList.Blink;

	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Flink->Blink = &deviceContext->DeferredLpxReceiveCompleteDpcPacketList;
	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Blink->Flink = &deviceContext->DeferredLpxReceiveCompleteDpcPacketList;

	InitializeListHead( &deviceContext->PacketInProgressList );

	// Perform actual LPX receive completion
	// If the completion is deferred, queue the DPC.
	// Some NIC drivers show receiving performance degrade
	// when receive complete routine consumes much CPU time.
	// Ex> Broadcom Giga ehternet 3788. driver name = b57nd60x.sys 11/1/2005/11:30 164KB

	LpxReferenceDeviceContext( "LpxReceiveComplete", deviceContext, DCREF_REQUEST );

	NDAS_ASSERT( deviceContext->DeferredLpxReceiveCompleteDpcRun == FALSE );

	queued = KeInsertQueueDpc( &deviceContext->DeferredLpxReceiveCompleteDpc, NULL, NULL );
	
	if (queued == FALSE) {

		NDAS_ASSERT(FALSE);
		LpxDereferenceDeviceContext( "LpxReceiveComplete", deviceContext, DCREF_REQUEST );		
	}

	deviceContext->DeferredLpxReceiveCompleteDpcRun = TRUE;

	RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );

	if (queued == FALSE) {

		LpxReceiveComplete2( BindingContext, &deviceContext->DeferredLpxReceiveCompleteDpcPacketList );

		ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
		deviceContext->DeferredLpxReceiveCompleteDpcRun = FALSE;
		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
	}

	return;
}