예제 #1
0
파일: protocol.c 프로젝트: GYGit/reactos
VOID NTAPI
ScatterGatherSendPacket(
   IN PDEVICE_OBJECT DeviceObject,
   IN PIRP Irp,
   IN PSCATTER_GATHER_LIST ScatterGather,
   IN PVOID Context)
{
   PDMA_CONTEXT DmaContext = Context;
   PLOGICAL_ADAPTER Adapter = DmaContext->Adapter;
   PNDIS_PACKET Packet = DmaContext->Packet;
   NDIS_STATUS Status;

   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));

   NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
                                    ScatterGatherListPacketInfo) = ScatterGather;

   Status = proSendPacketToMiniport(Adapter, Packet);

   if (Status != NDIS_STATUS_PENDING) {
       NDIS_DbgPrint(MAX_TRACE, ("Completing packet.\n"));
       MiniSendComplete(Adapter,
                        Packet,
                        Status);
   }

   ExFreePool(DmaContext);
}
/*----------------------------------------------------------------------------*/
VOID kalQueryTxChksumOffloadParam(IN PVOID pvPacket, OUT PUINT_8 pucFlag)
{
	PNDIS_PACKET prPacket = (PNDIS_PACKET) pvPacket;
	NDIS_TCP_IP_CHECKSUM_PACKET_INFO rChecksumPktInfo;
	UINT_8 ucFlag = 0;

	if (NDIS_GET_PACKET_PROTOCOL_TYPE(prPacket) == NDIS_PROTOCOL_ID_TCP_IP) {

		rChecksumPktInfo.Value = (UINT_32)
		    NDIS_PER_PACKET_INFO_FROM_PACKET(prPacket, TcpIpChecksumPacketInfo);

		/* TODO: need to check NIC_CHECKSUM_OFFLOAD from glue_info ?? */
		if (rChecksumPktInfo.Transmit.NdisPacketChecksumV4 ||
		    rChecksumPktInfo.Transmit.NdisPacketChecksumV6) {

			/* only apply checksum offload for IPv4 packets */
			if (rChecksumPktInfo.Transmit.NdisPacketIpChecksum) {
				ucFlag |= TX_CS_IP_GEN;
			}

			if (rChecksumPktInfo.Transmit.NdisPacketTcpChecksum ||
			    rChecksumPktInfo.Transmit.NdisPacketUdpChecksum) {
				ucFlag |= TX_CS_TCP_UDP_GEN;
			}
		}
	}
	*pucFlag = ucFlag;

}				/* kalQueryChksumOffloadParam */
예제 #3
0
//***********************************************************************************
// Name: MpProcessSGList 
//
// Description: 
//		starts a direct memory access (DMA) scatter/gather operation.
//
// Return value: 
//		None
//
// Parameters: 
//
// NOTE: None
// **********************************************************************************
VOID
	MpProcessSGList(
		IN	PDEVICE_OBJECT			pDO,
		IN	PIRP					pIrp,
		IN	PSCATTER_GATHER_LIST	pSGL,
		IN	PVOID					Context
		)
{
	NDIS_STATUS nStatus;
	PNDIS_PACKET Packet = (PNDIS_PACKET)Context;
	PKIP_PACKET_CONTEXT PacketContext = NDIS_PER_PACKET_CONTEXT(Packet);
	PKIP_NDIS_PROTOCOL pProtocol = PacketContext->pProtocol;
	PKIP_NDIS_ADAPTER pAdapter = (PKIP_NDIS_ADAPTER)pProtocol->pInterface;
	PKIP_NDIS_MINIPORT pMiniport = pAdapter->Interface.Miniport;
	//PNDIS_CO_VC_PTR_BLOCK	VcPtr;

	NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo) = pSGL;

	//
	// Handle Send/SendPacket differently
	//
	//MINIPORT_SET_PACKET_FLAG(Packet, fPACKET_PENDING);
	if (KIP_MINIPORT_TEST_FLAG(pAdapter, fADAPTER_IS_CO))
	{
		//VcPtr = GET_VCPTR_FROM_PACKET(Packet);
		//(*VcPtr->WCoSendPacketsHandler)(VcPtr->MiniportContext,
		//								&Packet,
		//								1);

		//TODO:
		ASSERT(FALSE);
	
	}
	else if ( pMiniport->Ndis5.MiniportCharacteristics.SendPacketsHandler )
	{
		pMiniport->Ndis5.MiniportCharacteristics.SendPacketsHandler(
			pAdapter->NdisMiniportAdapterContext,
			&Packet, 1
			);
	} 
	else if ( pMiniport->Ndis5.MiniportCharacteristics.SendHandler ){
		nStatus = 
			pMiniport->Ndis5.MiniportCharacteristics.SendHandler(
				pAdapter->NdisMiniportAdapterContext,
				Packet, 0
				);

		// if not pending then complete it
		if (nStatus != NDIS_STATUS_PENDING)
		{
			MpSendPacketCompleteHandler( pAdapter, Packet, nStatus );
		}
	}
}
예제 #4
0
//***********************************************************************************
// Name: MpFreeSGList 
//
// Description: 
//		frees sgdma list
//
// Return value: 
//		None
//
// Parameters: 
//
// NOTE: None
// **********************************************************************************
VOID
	MpFreeSGList(
		IN  PKIP_NDIS_ADAPTER		pAdapter,
		IN	PNDIS_PACKET			Packet
		)
{
	PSCATTER_GATHER_LIST pSGL;
	PDMA_ADAPTER	SystemAdapterObject = NDIS_GetSystemAdapterObject( pAdapter->NdisMiniportHandle );

	pSGL = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo);
	if ( SystemAdapterObject ){
		SystemAdapterObject->DmaOperations->PutScatterGatherList( SystemAdapterObject, pSGL, TRUE );
	}

	if ( (Packet->Private.Flags & NDIS_FLAGS_USES_SG_BUFFER_LIST ) ==  NDIS_FLAGS_USES_SG_BUFFER_LIST ){
		PNPAGED_LOOKASIDE_LIST SGListLookasideList = NDIS_GetSGListLookasideList( pAdapter->NdisMiniportHandle );
		Packet->Private.Flags &= ~NDIS_FLAGS_USES_SG_BUFFER_LIST;
		pSGL = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, NdisReserved);
		if ( pSGL && SGListLookasideList ){
			ExFreeToNPagedLookasideList( SGListLookasideList, pSGL );
		}
		NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, NdisReserved) = NULL;
	} 
	else if ( ( Packet->Private.Flags & NDIS_FLAGS_DOUBLE_BUFFERED ) == NDIS_FLAGS_DOUBLE_BUFFERED ){
		PNDIS_BUFFER NdisBuffer;
		PVOID NdisBufferVA;
		Packet->Private.Flags &= ~NDIS_FLAGS_DOUBLE_BUFFERED;
		NdisBuffer = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, NdisReserved);
		if ( NdisBuffer ){
			NdisBufferVA = MmGetMdlVirtualAddress(NdisBuffer);
			NdisFreeBuffer( NdisBuffer );
			if ( NdisBufferVA ){
				ExFreePoolWithTag(NdisBufferVA,MODULE_TAG);
			}
		}
	}
}
예제 #5
0
/* Maps to ReceiverReceiveNetBufferList() in xennet6 */
static NTSTATUS
ReceiverReceivePacket(
    IN  PRECEIVER       Receiver,
    OUT PNDIS_PACKET    *pPacket,
    OUT ULONG           *pTotFrags
    )
{
    struct ethhdr *eh;
    PNDIS_PACKET work;
    NDIS_STATUS stat;
    PNDIS_BUFFER buffer;
    uint16_t head_flags;
    UINT buffer_length;
    ULONG totOctets;
    ULONG totFrags;
    PMP_RFD prefixRfd;
    PMP_RFD headRfd;

    stat = ReceiverCommonReceiveRfdChain(Receiver, &head_flags, &prefixRfd,
                                         &headRfd, &totOctets, &totFrags);
    if (stat != NDIS_STATUS_SUCCESS) {
        Receiver->Common.Adapter->RxError++;
        goto discard;
    }
    XM_ASSERT(totFrags > 0);

    /* There should never be a prefix as we do not enable GSO on the
       receive path. */
    XM_ASSERT(prefixRfd == NULL);

    NdisDprAllocatePacketNonInterlocked(&stat, &work,
                                        Receiver->RecvPacketPool);
    if (stat != NDIS_STATUS_SUCCESS) {
        Receiver->nRxDiscards++;
        goto discard;
    }

    NDIS_SET_PACKET_HEADER_SIZE(work, XENNET_PACKET_HDR_SIZE);
    NdisChainBufferAtFront(work, &headRfd->Mdl);

    /* Ick: find the ethernet and IP headers so that we can check (a)
       the MAC address is for us, and (b) whether to indicate RX csum
       offload.  We rely on the fact that netback always puts the
       ethernet and IP headers in the same fragment. */

    buffer = &headRfd->Mdl;
    buffer_length = buffer->ByteCount;

    stat = STATUS_UNSUCCESSFUL;
    if (buffer_length < sizeof(struct ethhdr)) {
        NdisDprFreePacketNonInterlocked(work);
        Receiver->nRxDiscards++;
        goto discard;
    }
        
    Receiver->Common.Adapter->RxGood++;

    eh = (struct ethhdr *)buffer->MappedSystemVa;

    stat = NDIS_STATUS_INVALID_PACKET;
    if (!MacAddressInteresting(eh->dest, Receiver->Common.Adapter)) {
        Receiver->Common.Adapter->MacMisdirect++;
        NdisDprFreePacketNonInterlocked(work);
        goto discard;
    }

    if (eh->proto == TPID_IPV4) {
        BOOLEAN needCsumFixup;
        NDIS_TCP_IP_CHECKSUM_PACKET_INFO CsumInfo;

        CsumInfo.Value = 0;

        needCsumFixup = (head_flags & NETRXF_csum_blank) ? TRUE : FALSE;

        if (head_flags & NETRXF_data_validated) {
            struct iphdr *ih = (struct iphdr *)(eh + 1);

            if (ih->proto == IPPROTO_TCP &&
                Receiver->rx_csum_tcp_offload) {
                CsumInfo.Receive.NdisPacketTcpChecksumSucceeded = 1;
                Receiver->nRxCsumOffload++;
            } else if (ih->proto == IPPROTO_UDP &&
                       Receiver->rx_csum_udp_offload) {
                CsumInfo.Receive.NdisPacketUdpChecksumSucceeded = 1;
                Receiver->nRxCsumOffload++;
            }
        }

        if (needCsumFixup) {
            FixupChecksum(work);
            Receiver->nRxCsumFixup++;
        }

        NDIS_PER_PACKET_INFO_FROM_PACKET(work, TcpIpChecksumPacketInfo) =
            (PVOID)(ULONG_PTR)CsumInfo.Value;
    }

    NDIS_SET_PACKET_STATUS(work, NDIS_STATUS_SUCCESS);

    *pPacket = work;
    *pTotFrags = totFrags;

    return NDIS_STATUS_SUCCESS;

discard:
    ReceiverCommonReleaseRfdChain(&Receiver->Common, prefixRfd);
    ReceiverCommonReleaseRfdChain(&Receiver->Common, headRfd);

    return stat;
}
예제 #6
0
파일: ndis.c 프로젝트: hoangduit/reactos
NDIS_STATUS
NTAPI
MiniportSend (
    IN NDIS_HANDLE MiniportAdapterContext,
    IN PNDIS_PACKET Packet,
    IN UINT Flags
    )
{
    PRTL_ADAPTER adapter = (PRTL_ADAPTER)MiniportAdapterContext;
    NDIS_STATUS status;
    PSCATTER_GATHER_LIST sgList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
                                    ScatterGatherListPacketInfo);
    ULONG transmitLength;
    ULONG transmitBuffer;
    PNDIS_BUFFER firstBuffer;
    PVOID firstBufferVa;
    UINT firstBufferLength, totalBufferLength;
    PUCHAR runtBuffer;

    ASSERT(sgList != NULL);
    
    ASSERT(sgList->NumberOfElements == 1);
    ASSERT(sgList->Elements[0].Address.HighPart == 0);
    ASSERT((sgList->Elements[0].Address.LowPart & 3) == 0);
    ASSERT(sgList->Elements[0].Length <= MAXIMUM_FRAME_SIZE);
    
    NDIS_DbgPrint(MAX_TRACE, ("Sending %d byte packet\n", sgList->Elements[0].Length));
    
    NdisAcquireSpinLock(&adapter->Lock);
    
    if (adapter->TxFull)
    {
        NDIS_DbgPrint(MIN_TRACE, ("All TX descriptors are full\n"));
        NdisReleaseSpinLock(&adapter->Lock);
        return NDIS_STATUS_RESOURCES;
    }
    
    NDIS_DbgPrint(MAX_TRACE, ("Sending packet on TX desc %d\n", adapter->CurrentTxDesc));
            
    //
    // If this is a runt, we need to pad it manually for the RTL8139
    //
    if (sgList->Elements[0].Length < MINIMUM_FRAME_SIZE)
    {
        transmitLength = MINIMUM_FRAME_SIZE;
        transmitBuffer = adapter->RuntTxBuffersPa.LowPart +
                  (MINIMUM_FRAME_SIZE * adapter->CurrentTxDesc);
                
        NdisGetFirstBufferFromPacketSafe(Packet,
                                         &firstBuffer,
                                         &firstBufferVa,
                                         &firstBufferLength,
                                         &totalBufferLength,
                                         NormalPagePriority);
        if (firstBufferVa == NULL)
        {
            NDIS_DbgPrint(MIN_TRACE, ("Unable to get buffer from packet\n"));
            NdisReleaseSpinLock(&adapter->Lock);
            return NDIS_STATUS_RESOURCES;
        }
                
        ASSERT(firstBufferLength == totalBufferLength);
               
        runtBuffer = adapter->RuntTxBuffers + (MINIMUM_FRAME_SIZE * adapter->CurrentTxDesc);
        RtlCopyMemory(runtBuffer, firstBufferVa, firstBufferLength);
        RtlFillMemory(runtBuffer + firstBufferLength, MINIMUM_FRAME_SIZE - firstBufferLength, 0x00);
    }
    else
    {
        transmitLength = sgList->Elements[0].Length;
        transmitBuffer = sgList->Elements[0].Address.LowPart;
    }

    status = NICTransmitPacket(adapter, adapter->CurrentTxDesc, transmitBuffer, transmitLength);
    if (status != NDIS_STATUS_SUCCESS)
    {
        NDIS_DbgPrint(MIN_TRACE, ("Transmit packet failed\n"));
        NdisReleaseSpinLock(&adapter->Lock);
        return status;
    }
        
    adapter->CurrentTxDesc++;
    adapter->CurrentTxDesc %= TX_DESC_COUNT;
    
    if (adapter->CurrentTxDesc == adapter->DirtyTxDesc)
    {
        NDIS_DbgPrint(MID_TRACE, ("All TX descriptors are full now\n"));
        adapter->TxFull = TRUE;
    }
    
    NdisReleaseSpinLock(&adapter->Lock);

    return NDIS_STATUS_SUCCESS;
}
예제 #7
0
//***********************************************************************************
// Name: MpAllocSGList
//
// Description: 
//		sends packet via DMA
//
// Return value: 
//		None
//
// Parameters: 
//
// NOTE: None
// **********************************************************************************
NDIS_STATUS
	MpAllocSGList(
		IN  PKIP_NDIS_ADAPTER		pAdapter,
		IN  PNDIS_PACKET            Packet
		)
{
	NDIS_STATUS		nStatus = NDIS_STATUS_FAILURE; 
	PNDIS_BUFFER	Buffer;
	PVOID			pBufferVa;
	ULONG			PacketLength;
	PDMA_ADAPTER	SystemAdapterObject;
	PDEVICE_OBJECT	DeviceObject;
	PNPAGED_LOOKASIDE_LIST SGListLookasideList = NULL;
	ULONG ScatterGatherListSize = 0;
	PVOID pSGList = NULL;
	KIRQL OldIrql;
	PVOID SendBuffer = NULL;
	PNDIS_BUFFER	SendNdisBuffer;
	ULONG nBytesRead = 0;
	BOOLEAN fbResult;
	BOOLEAN fbDMAV2;

	do 
	{
		SystemAdapterObject = NDIS_GetSystemAdapterObject( pAdapter->NdisMiniportHandle );
		if ( SystemAdapterObject == NULL ){
			DBGLOG(( LError, "SystemAdapterObject is NULL\n" ));
			nStatus = NDIS_STATUS_RESOURCES;
			break;
		}

		fbDMAV2 = (SystemAdapterObject->DmaOperations->Size >= sizeof(DMA_OPERATIONS_V2) );

		DeviceObject = NDIS_GetMiniportDeviceObject( pAdapter->NdisMiniportHandle );
		if ( DeviceObject == NULL ){
			DBGLOG(( LError, "DeviceObject is NULL\n" ));
			nStatus = NDIS_STATUS_RESOURCES;
			break;
		}

		if ( fbDMAV2 ){
			SGListLookasideList = NDIS_GetSGListLookasideList( pAdapter->NdisMiniportHandle );
			if ( SGListLookasideList == NULL ){
				DBGLOG(( LError, "SGListLookasideList is NULL\n" ));
				nStatus = NDIS_STATUS_RESOURCES;
				break;
			}

			ScatterGatherListSize = NDIS_GetScatterGatherListSize( pAdapter->NdisMiniportHandle );
			if ( ScatterGatherListSize == 0 ){
				DBGLOG(( LError, "SGListLookasideList is NULL\n" ));
				nStatus = NDIS_STATUS_RESOURCES;
				break;
			}
		}

		NdisQueryPacket(Packet, NULL, NULL, &Buffer, &PacketLength);
		if ( Buffer == NULL ){
			DBGLOG(( LError, "Buffer is NULL\n" ));
			nStatus = NDIS_STATUS_FAILURE;
			break;
		}

		// try to use build sg list interface
		if ( fbDMAV2 ){
			// allocate SG list
			pSGList = 
				ExAllocateFromNPagedLookasideList(
					SGListLookasideList
					);
			if ( pSGList != NULL ){

				Packet->Private.Flags |= NDIS_FLAGS_USES_SG_BUFFER_LIST; // sg list
				NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, NdisReserved) = pSGList;
				// raise irql to dispatch
				KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
				nStatus = 
					SystemAdapterObject->DmaOperations->BuildScatterGatherList(
						SystemAdapterObject,
						DeviceObject,
						Buffer,
						MmGetMdlVirtualAddress(Buffer),
						PacketLength,
						MpProcessSGList,
						Packet,
						TRUE,
						pSGList,
						ScatterGatherListSize
						);
				KeLowerIrql( OldIrql );

				if ( !NT_SUCCESS ( nStatus )){
					DBGLOG(( LDebug, "%08X=BuildMdlFromScatterGatherList failed\n",nStatus ));
					Packet->Private.Flags &= ~NDIS_FLAGS_RESERVED2; // sg list
					NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo) = NULL;
					ExFreeToNPagedLookasideList( SGListLookasideList, pSGList );
				}
			}else{
				DBGLOG(( LDebug, "ExAllocateFromNPagedLookasideList failed\n" ));
				nStatus = NDIS_STATUS_RESOURCES;
			}
		}

		// if ( !fbDMAV2 ) then nStatus = NDIS_STATUS_FAILURE; 
		if ( !NT_SUCCESS ( nStatus ))
		{
			// raise irql to dispatch
			KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);

			// call DMA
			nStatus = 
				SystemAdapterObject->DmaOperations->GetScatterGatherList(
					SystemAdapterObject,
					DeviceObject,
					Buffer,
					MmGetMdlVirtualAddress(Buffer),
					PacketLength,
					MpProcessSGList,
					Packet,
					TRUE
					);
			KeLowerIrql( OldIrql );

			if ( !NT_SUCCESS ( nStatus )){
				DBGLOG(( LError, "%08X=GetScatterGatherList failed\n",nStatus ));
			}
		}

		if ( fbDMAV2 && !NT_SUCCESS ( nStatus ) ) {
			
			SendBuffer = 
				ExAllocatePoolWithTag(
					NonPagedPool,
					PacketLength,
					MODULE_TAG
					);
			if ( SendBuffer == NULL ){
				DBGLOG(( LError, "ExAllocatePoolWithTag failed\n" ));
				nStatus = NDIS_STATUS_RESOURCES;
				break;
			}
			NdisAllocateBuffer(
				&nStatus,
				&SendNdisBuffer,
				NULL,
				SendBuffer,
				PacketLength
				);

			if ( nStatus != NDIS_STATUS_SUCCESS ){
				DBGLOG(( LError, "%08X=NdisAllocateBuffer failed\n",nStatus ));
				break;
			}
			//copy data to intermediate buffer
			fbResult =
				NDIS_CopyPacketData(
					Packet,
					SendBuffer,
					PacketLength,0,
					&nBytesRead
					);
			if ( !fbResult || nBytesRead != PacketLength ){
				DBGLOG(( LError, "NDIS_CopyPacketData failed\n" ));
				nStatus = NDIS_STATUS_RESOURCES;
				break;
			}

			Packet->Private.Flags |= NDIS_FLAGS_DOUBLE_BUFFERED; // sg list
			NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, NdisReserved) = SendBuffer;

			// raise irql to dispatch
			KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
			// call DMA
			nStatus = 
				SystemAdapterObject->DmaOperations->GetScatterGatherList(
					SystemAdapterObject,
					DeviceObject,
					SendNdisBuffer,
					MmGetMdlVirtualAddress(SendNdisBuffer),
					PacketLength,
					MpProcessSGList,
					Packet,
					TRUE
					);
			KeLowerIrql( OldIrql );			
		}

		if ( !NT_SUCCESS ( nStatus ) ){

			if ( SendNdisBuffer ){
				NdisFreeBuffer( SendNdisBuffer );
			}
			if ( SendBuffer ){
				ExFreePoolWithTag( SendBuffer, MODULE_TAG );
			}

			NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, NdisReserved) = NULL;
			if (KIP_MINIPORT_TEST_FLAG(pAdapter, fADAPTER_IS_CO))
			{
				ASSERT(FALSE); // TODO:
				//NdisMCoSendComplete(NDIS_STATUS_FAILURE, GET_VCPTR_FROM_PACKET(Packet), Packet);
			}
			else
			{
				//MpSendPacketCompleteHandler( pAdapter, Packet, NDIS_STATUS_FAILURE );
				// we complete it in caller
			}
		}

	} while ( FALSE );

	return nStatus;
}