Author: cgutman
Date: Wed Oct  5 20:36:20 2011
New Revision: 54016

URL: http://svn.reactos.org/svn/reactos?rev=54016&view=rev
Log:
[HAL]
- Implement support for scatter/gather DMA
- Tested with Intel's NDIS 5.1 PRO/1000 driver (but more testing would be 
helpful to weed out bugs)
[NDIS]
- Report NDIS 5.1 now since S/G DMA is supported
- Stop warning when S/G DMA is used

Modified:
    trunk/reactos/drivers/network/ndis/include/ndissys.h
    trunk/reactos/drivers/network/ndis/ndis/protocol.c
    trunk/reactos/hal/halx86/generic/dma.c

Modified: trunk/reactos/drivers/network/ndis/include/ndissys.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/ndis/include/ndissys.h?rev=54016&r1=54015&r2=54016&view=diff
==============================================================================
--- trunk/reactos/drivers/network/ndis/include/ndissys.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/ndis/include/ndissys.h [iso-8859-1] Wed Oct  
5 20:36:20 2011
@@ -30,7 +30,7 @@
 #endif
 
 /* the version of NDIS we claim to be */
-#define NDIS_VERSION 0x00050000
+#define NDIS_VERSION 0x00050001
 
 #define NDIS_TAG  0x4e4d4953
 

Modified: trunk/reactos/drivers/network/ndis/ndis/protocol.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/ndis/ndis/protocol.c?rev=54016&r1=54015&r2=54016&view=diff
==============================================================================
--- trunk/reactos/drivers/network/ndis/ndis/protocol.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/ndis/ndis/protocol.c [iso-8859-1] Wed Oct  5 
20:36:20 2011
@@ -516,7 +516,7 @@
     } else {
         if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
         {
-            NDIS_DbgPrint(MIN_TRACE, ("Using Scatter/Gather DMA\n"));
+            NDIS_DbgPrint(MID_TRACE, ("Using Scatter/Gather DMA\n"));
 
             NdisQueryPacket(Packet,
                             NULL,

Modified: trunk/reactos/hal/halx86/generic/dma.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/dma.c?rev=54016&r1=54015&r2=54016&view=diff
==============================================================================
--- trunk/reactos/hal/halx86/generic/dma.c [iso-8859-1] (original)
+++ trunk/reactos/hal/halx86/generic/dma.c [iso-8859-1] Wed Oct  5 20:36:20 2011
@@ -74,6 +74,8 @@
 #include <hal.h>
 #define NDEBUG
 #include <debug.h>
+
+#define MAX_SG_ELEMENTS 0x10
 
 #ifndef _MINIHAL_
 static KEVENT HalpDmaLock;
@@ -110,8 +112,8 @@
    (PGET_DMA_ALIGNMENT)HalpDmaGetDmaAlignment,
    (PREAD_DMA_COUNTER)HalReadDmaCounter,
    /* FIXME: Implement the S/G funtions. */
-   NULL /*(PGET_SCATTER_GATHER_LIST)HalGetScatterGatherList*/,
-   NULL /*(PPUT_SCATTER_GATHER_LIST)HalPutScatterGatherList*/,
+   (PGET_SCATTER_GATHER_LIST)HalGetScatterGatherList,
+   (PPUT_SCATTER_GATHER_LIST)HalPutScatterGatherList,
    NULL 
/*(PCALCULATE_SCATTER_GATHER_LIST_SIZE)HalCalculateScatterGatherListSize*/,
    NULL /*(PBUILD_SCATTER_GATHER_LIST)HalBuildScatterGatherList*/,
    NULL 
/*(PBUILD_MDL_FROM_SCATTER_GATHER_LIST)HalBuildMdlFromScatterGatherList*/
@@ -907,6 +909,192 @@
     MmFreeContiguousMemorySpecifyCache(VirtualAddress,
                                        Length,
                                        CacheEnabled ? MmCached : MmNonCached);
+}
+
+typedef struct _SCATTER_GATHER_CONTEXT {
+       PADAPTER_OBJECT AdapterObject;
+       PMDL Mdl;
+       PUCHAR CurrentVa;
+       ULONG Length;
+       PDRIVER_LIST_CONTROL AdapterListControlRoutine;
+       PVOID AdapterListControlContext, MapRegisterBase;
+       ULONG MapRegisterCount;
+       BOOLEAN WriteToDevice;
+} SCATTER_GATHER_CONTEXT, *PSCATTER_GATHER_CONTEXT;
+       
+
+IO_ALLOCATION_ACTION
+NTAPI
+HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
+                                IN PIRP Irp,
+                                                               IN PVOID 
MapRegisterBase,
+                                                               IN PVOID 
Context)
+{
+       PSCATTER_GATHER_CONTEXT AdapterControlContext = Context;
+       PADAPTER_OBJECT AdapterObject = AdapterControlContext->AdapterObject;
+       PSCATTER_GATHER_LIST ScatterGatherList;
+       SCATTER_GATHER_ELEMENT TempElements[MAX_SG_ELEMENTS];
+       ULONG ElementCount = 0, RemainingLength = AdapterControlContext->Length;
+       PUCHAR CurrentVa = AdapterControlContext->CurrentVa;
+       
+       /* Store the map register base for later in HalPutScatterGatherList */
+       AdapterControlContext->MapRegisterBase = MapRegisterBase;
+       
+       while (RemainingLength > 0 && ElementCount < MAX_SG_ELEMENTS)
+       {
+           TempElements[ElementCount].Length = RemainingLength;
+               TempElements[ElementCount].Reserved = 0;
+           TempElements[ElementCount].Address = IoMapTransfer(AdapterObject,
+                                                                  
AdapterControlContext->Mdl,
+                                                                               
                                   MapRegisterBase,
+                                                                               
                                   CurrentVa + (AdapterControlContext->Length - 
RemainingLength),
+                                                                               
                                   &TempElements[ElementCount].Length,
+                                                                               
                                   AdapterControlContext->WriteToDevice);
+               if (TempElements[ElementCount].Length == 0)
+                       break;
+                       
+               DPRINT("Allocated one S/G element: 0x%I64u with length: 0x%x\n",
+                       TempElements[ElementCount].Address.QuadPart,
+                               TempElements[ElementCount].Length);
+               
+               ASSERT(TempElements[ElementCount].Length <= RemainingLength);
+               RemainingLength -= TempElements[ElementCount].Length;
+               ElementCount++;
+       }
+       
+       if (RemainingLength > 0)
+       {
+               DPRINT1("Scatter/gather list construction failed!\n");
+               return DeallocateObject;
+       }
+
+       ScatterGatherList = ExAllocatePoolWithTag(NonPagedPool,
+                                                 sizeof(SCATTER_GATHER_LIST) + 
sizeof(SCATTER_GATHER_ELEMENT) * ElementCount,
+                                                                               
          TAG_DMA);
+       ASSERT(ScatterGatherList);
+
+       ScatterGatherList->NumberOfElements = ElementCount;
+       ScatterGatherList->Reserved = (ULONG_PTR)AdapterControlContext;
+       RtlCopyMemory(ScatterGatherList->Elements,
+                     TempElements,
+                                 sizeof(SCATTER_GATHER_ELEMENT) * 
ElementCount);
+                                 
+       DPRINT("Initiating S/G DMA with %d element(s)\n", ElementCount);
+       
+       AdapterControlContext->AdapterListControlRoutine(DeviceObject,
+                                                        Irp,
+                                                                               
                         ScatterGatherList,
+                                                                               
                         AdapterControlContext->AdapterListControlContext);
+                                                                               
                         
+       return DeallocateObjectKeepRegisters;
+}
+
+/**
+ * @name HalGetScatterGatherList
+ *
+ * Creates a scatter-gather list to be using in scatter/gather DMA
+ *
+ * @param AdapterObject
+ *        Adapter object representing the bus master or system dma controller.
+ * @param DeviceObject
+ *        The device target for DMA.
+ * @param Mdl
+ *        The MDL that describes the buffer to be mapped.
+ * @param CurrentVa
+ *        The current VA in the buffer to be mapped for transfer.
+ * @param Length
+ *        Specifies the length of data in bytes to be mapped.
+ * @param ExecutionRoutine
+ *        A caller supplied AdapterListControl routine to be called when DMA 
is available.
+ * @param Context
+ *        Context passed to the AdapterListControl routine.
+ * @param WriteToDevice
+ *        Indicates direction of DMA operation.
+ *
+ * @return The status of the operation.
+ *
+ * @see HalPutScatterGatherList
+ *
+ * @implemented
+ */
+ NTSTATUS
+ NTAPI
+ HalGetScatterGatherList(IN PADAPTER_OBJECT AdapterObject,
+                         IN PDEVICE_OBJECT DeviceObject,
+                                                IN PMDL Mdl,
+                                                IN PVOID CurrentVa,
+                                                IN ULONG Length,
+                                                IN PDRIVER_LIST_CONTROL 
ExecutionRoutine,
+                                                IN PVOID Context,
+                                                IN BOOLEAN WriteToDevice)
+{
+       PSCATTER_GATHER_CONTEXT AdapterControlContext;
+       
+       AdapterControlContext = ExAllocatePoolWithTag(NonPagedPool, 
sizeof(SCATTER_GATHER_CONTEXT), TAG_DMA);
+       if (!AdapterControlContext) return STATUS_INSUFFICIENT_RESOURCES;
+       
+       AdapterControlContext->AdapterObject = AdapterObject;
+       AdapterControlContext->Mdl = Mdl;
+       AdapterControlContext->CurrentVa = CurrentVa;
+       AdapterControlContext->Length = Length;
+       AdapterControlContext->MapRegisterCount = PAGE_ROUND_UP(Length) >> 
PAGE_SHIFT;
+       AdapterControlContext->AdapterListControlRoutine = ExecutionRoutine;
+       AdapterControlContext->AdapterListControlContext = Context;
+       AdapterControlContext->WriteToDevice = WriteToDevice;
+       
+       return IoAllocateAdapterChannel(AdapterObject,
+                                       DeviceObject,
+                                                                       
AdapterControlContext->MapRegisterCount,
+                                                                       
HalpScatterGatherAdapterControl,
+                                                                       
AdapterControlContext);
+}
+
+/**
+ * @name HalPutScatterGatherList
+ *
+ * Frees a scatter-gather list allocated from HalGetScatterGatherList
+ *
+ * @param AdapterObject
+ *        Adapter object representing the bus master or system dma controller.
+ * @param ScatterGather
+ *        The scatter/gather list to be freed.
+ * @param WriteToDevice
+ *        Indicates direction of DMA operation.
+ *
+ * @return None
+ *
+ * @see HalGetScatterGatherList
+ *
+ * @implemented
+ */
+ VOID
+ NTAPI
+ HalPutScatterGatherList(IN PADAPTER_OBJECT AdapterObject,
+                         IN PSCATTER_GATHER_LIST ScatterGather,
+                                                IN BOOLEAN WriteToDevice)
+{
+    PSCATTER_GATHER_CONTEXT AdapterControlContext = 
(PSCATTER_GATHER_CONTEXT)ScatterGather->Reserved;
+       ULONG i;
+       
+       for (i = 0; i < ScatterGather->NumberOfElements; i++)
+       {
+            IoFlushAdapterBuffers(AdapterObject,
+                                      AdapterControlContext->Mdl,
+                                                          
AdapterControlContext->MapRegisterBase,
+                                                          
AdapterControlContext->CurrentVa,
+                                                          
ScatterGather->Elements[i].Length,
+                                                          
AdapterControlContext->WriteToDevice);
+                AdapterControlContext->CurrentVa += 
ScatterGather->Elements[i].Length;
+       }
+
+       IoFreeMapRegisters(AdapterObject,
+                          AdapterControlContext->MapRegisterBase,
+                                          
AdapterControlContext->MapRegisterCount);
+                                          
+       DPRINT("S/G DMA has finished!\n");
+       
+       ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
+       ExFreePoolWithTag(ScatterGather, TAG_DMA);
 }
 #endif
 


Reply via email to