diff --git a/reactos/drivers/network/ndis/include/protocol.h b/reactos/drivers/network/ndis/include/protocol.h index 4737f213226..ecebc2d118c 100644 --- a/reactos/drivers/network/ndis/include/protocol.h +++ b/reactos/drivers/network/ndis/include/protocol.h @@ -67,6 +67,9 @@ NdisIPnPCancelStopDevice( IN PDEVICE_OBJECT DeviceObject, PIRP Irp); +NDIS_STATUS +proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet); + #endif /* __PROTOCOL_H */ /* EOF */ diff --git a/reactos/drivers/network/ndis/ndis/io.c b/reactos/drivers/network/ndis/ndis/io.c index b7cc89c638a..0be8df54086 100644 --- a/reactos/drivers/network/ndis/ndis/io.c +++ b/reactos/drivers/network/ndis/ndis/io.c @@ -944,12 +944,6 @@ NdisMInitializeScatterGatherDma( if (!(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER)) return NDIS_STATUS_NOT_SUPPORTED; - if (Adapter->NdisMiniportBlock.SystemAdapterObject) - { - NDIS_DbgPrint(MIN_TRACE,("Using existing DMA adapter\n")); - return NDIS_STATUS_SUCCESS; - } - RtlZeroMemory(&DeviceDesc, sizeof(DEVICE_DESCRIPTION)); DeviceDesc.Version = DEVICE_DESCRIPTION_VERSION; @@ -967,6 +961,9 @@ NdisMInitializeScatterGatherDma( if (!Adapter->NdisMiniportBlock.SystemAdapterObject) return NDIS_STATUS_RESOURCES; + /* FIXME: Right now we just use this as a place holder */ + Adapter->NdisMiniportBlock.ScatterGatherListSize = 1; + return NDIS_STATUS_SUCCESS; } diff --git a/reactos/drivers/network/ndis/ndis/miniport.c b/reactos/drivers/network/ndis/ndis/miniport.c index 47dede75170..c49c27d2f4f 100644 --- a/reactos/drivers/network/ndis/ndis/miniport.c +++ b/reactos/drivers/network/ndis/ndis/miniport.c @@ -430,18 +430,40 @@ MiniSendComplete( * Status = Status of send operation */ { + PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle; PADAPTER_BINDING AdapterBinding; KIRQL OldIrql; + PSCATTER_GATHER_LIST SGList; NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n")); AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1]; KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + + /* Should we free this before or after calling SendComplete? */ + if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0) + { + NDIS_DbgPrint(MAX_TRACE, ("Freeing Scatter/Gather list\n")); + + SGList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, + ScatterGatherListPacketInfo); + + Adapter->NdisMiniportBlock.SystemAdapterObject-> + DmaOperations->PutScatterGatherList( + Adapter->NdisMiniportBlock.SystemAdapterObject, + SGList, + TRUE); + + NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, + ScatterGatherListPacketInfo) = NULL; + } + (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)( AdapterBinding->NdisOpenBlock.ProtocolBindingContext, Packet, Status); + KeLowerIrql(OldIrql); } diff --git a/reactos/drivers/network/ndis/ndis/protocol.c b/reactos/drivers/network/ndis/ndis/protocol.c index ffc276f1ed8..bfb07420814 100644 --- a/reactos/drivers/network/ndis/ndis/protocol.c +++ b/reactos/drivers/network/ndis/ndis/protocol.c @@ -22,6 +22,11 @@ KSPIN_LOCK ProtocolListLock; #define WORKER_TEST 0 +typedef struct _DMA_CONTEXT { + PLOGICAL_ADAPTER Adapter; + PNDIS_PACKET Packet; +} DMA_CONTEXT, *PDMA_CONTEXT; + PNET_PNP_EVENT ProSetupPnPEvent( NET_PNP_EVENT_CODE EventCode, @@ -327,6 +332,33 @@ ProReset( return NDIS_STATUS_FAILURE; } +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); + } +} + NDIS_STATUS proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet) { @@ -412,6 +444,11 @@ ProSend( { PADAPTER_BINDING AdapterBinding; PLOGICAL_ADAPTER Adapter; + PNDIS_BUFFER NdisBuffer; + PDMA_CONTEXT Context; + NDIS_STATUS NdisStatus; + UINT PacketLength; + KIRQL OldIrql; NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); @@ -447,6 +484,48 @@ ProSend( return ProIndicatePacket(Adapter, Packet); #endif } else { + if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0) + { + NDIS_DbgPrint(MAX_TRACE, ("Using Scatter/Gather DMA\n")); + + NdisQueryPacket(Packet, + NULL, + NULL, + &NdisBuffer, + &PacketLength); + + Context = ExAllocatePool(NonPagedPool, sizeof(DMA_CONTEXT)); + if (!Context) + return NDIS_STATUS_RESOURCES; + + Context->Adapter = Adapter; + Context->Packet = Packet; + + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + + KeFlushIoBuffers(NdisBuffer, FALSE, TRUE); + + NdisStatus = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->GetScatterGatherList( + Adapter->NdisMiniportBlock.SystemAdapterObject, + Adapter->NdisMiniportBlock.PhysicalDeviceObject, + NdisBuffer, + MmGetMdlVirtualAddress(NdisBuffer), + PacketLength, + ScatterGatherSendPacket, + Context, + TRUE); + + KeLowerIrql(OldIrql); + + if (!NT_SUCCESS(NdisStatus)) { + NDIS_DbgPrint(MIN_TRACE, ("GetScatterGatherList failed!\n")); + return NdisStatus; + } + + return NDIS_STATUS_PENDING; + } + + return proSendPacketToMiniport(Adapter, Packet); } }