[HALX86] Implement HalBuildScatterGatherList
authorHervé Poussineau <hpoussin@reactos.org>
Sun, 7 Nov 2021 11:18:04 +0000 (12:18 +0100)
committerHervé Poussineau <hpoussin@reactos.org>
Sun, 7 Nov 2021 13:07:57 +0000 (14:07 +0100)
Make HalGetScatterGatherList a wrapper around it.

hal/halx86/generic/dma.c

index f14bbf5..19d7051 100644 (file)
@@ -974,6 +974,7 @@ HalFreeCommonBuffer(IN PADAPTER_OBJECT AdapterObject,
 }
 
 typedef struct _SCATTER_GATHER_CONTEXT {
+    BOOLEAN UsingUserBuffer;
        PADAPTER_OBJECT AdapterObject;
        PMDL Mdl;
        PUCHAR CurrentVa;
@@ -1076,7 +1077,7 @@ HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
  *
  * @return The status of the operation.
  *
- * @see HalPutScatterGatherList
+ * @see HalBuildScatterGatherList
  *
  * @implemented
  */
@@ -1084,41 +1085,29 @@ HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
  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)
+                         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;
-
-       AdapterControlContext->Wcb.DeviceObject = DeviceObject;
-       AdapterControlContext->Wcb.DeviceContext = AdapterControlContext;
-       AdapterControlContext->Wcb.CurrentIrp = DeviceObject->CurrentIrp;
-
-       return HalAllocateAdapterChannel(AdapterObject,
-               &AdapterControlContext->Wcb,
-               AdapterControlContext->MapRegisterCount,
-               HalpScatterGatherAdapterControl);
+    return HalBuildScatterGatherList(AdapterObject,
+                                     DeviceObject,
+                                     Mdl,
+                                     CurrentVa,
+                                     Length,
+                                     ExecutionRoutine,
+                                     Context,
+                                     WriteToDevice,
+                                     NULL,
+                                     0);
 }
 
 /**
  * @name HalPutScatterGatherList
  *
- * Frees a scatter-gather list allocated from HalGetScatterGatherList
+ * Frees a scatter-gather list allocated from HalBuildScatterGatherList
  *
  * @param AdapterObject
  *        Adapter object representing the bus master or system dma controller.
@@ -1129,7 +1118,7 @@ HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
  *
  * @return None
  *
- * @see HalGetScatterGatherList
+ * @see HalBuildScatterGatherList
  *
  * @implemented
  */
@@ -1157,10 +1146,14 @@ HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
                           AdapterControlContext->MapRegisterBase,
                                           AdapterControlContext->MapRegisterCount);
 
-       DPRINT("S/G DMA has finished!\n");
 
-       ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
        ExFreePoolWithTag(ScatterGather, TAG_DMA);
+
+    /* If this is our buffer, release it */
+    if (!AdapterControlContext->UsingUserBuffer)
+        ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
+
+    DPRINT("S/G DMA has finished!\n");
 }
 
 NTSTATUS
@@ -1187,6 +1180,40 @@ HalCalculateScatterGatherListSize(
     return STATUS_SUCCESS;
 }
 
+/**
+ * @name HalBuildScatterGatherList
+ *
+ * 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.
+ *
+ * @param ScatterGatherBuffer
+ *        User buffer for the scatter-gather list
+ *
+ * @param ScatterGatherBufferLength
+ *        Buffer length
+ *
+ * @return The status of the operation.
+ *
+ * @see HalPutScatterGatherList
+ *
+ * @implemented
+ */
 NTSTATUS
 NTAPI
 HalBuildScatterGatherList(
@@ -1199,10 +1226,72 @@ HalBuildScatterGatherList(
     IN PVOID Context,
     IN BOOLEAN WriteToDevice,
     IN PVOID ScatterGatherBuffer,
-    IN ULONG ScatterGatherLength)
+    IN ULONG ScatterGatherBufferLength)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    ULONG SgSize, NumberOfMapRegisters;
+    PSCATTER_GATHER_CONTEXT ScatterGatherContext;
+    BOOLEAN UsingUserBuffer;
+
+    Status = HalCalculateScatterGatherListSize(AdapterObject,
+                                               Mdl,
+                                               CurrentVa,
+                                               Length,
+                                               &SgSize,
+                                               &NumberOfMapRegisters);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    if (ScatterGatherBuffer)
+    {
+        /* Checking if user buffer is enough */
+        if (ScatterGatherBufferLength < SgSize)
+        {
+            return STATUS_BUFFER_TOO_SMALL;
+        }
+        UsingUserBuffer = TRUE;
+    }
+    else
+    {
+        ScatterGatherBuffer = ExAllocatePoolWithTag(NonPagedPool, SgSize, TAG_DMA);
+        if (!ScatterGatherBuffer)
+        {
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+        UsingUserBuffer = FALSE;
+    }
+
+    {
+        ScatterGatherContext = (PSCATTER_GATHER_CONTEXT)ScatterGatherBuffer;
+
+        /* Fill the scatter-gather context */
+        ScatterGatherContext->UsingUserBuffer = UsingUserBuffer;
+        ScatterGatherContext->AdapterObject = AdapterObject;
+        ScatterGatherContext->Mdl = Mdl;
+        ScatterGatherContext->CurrentVa = CurrentVa;
+        ScatterGatherContext->Length = Length;
+        ScatterGatherContext->MapRegisterCount = NumberOfMapRegisters;
+        ScatterGatherContext->AdapterListControlRoutine = ExecutionRoutine;
+        ScatterGatherContext->AdapterListControlContext = Context;
+        ScatterGatherContext->WriteToDevice = WriteToDevice;
+
+        ScatterGatherContext->Wcb.DeviceObject = DeviceObject;
+        ScatterGatherContext->Wcb.DeviceContext = (PVOID)ScatterGatherContext;
+        ScatterGatherContext->Wcb.CurrentIrp = DeviceObject->CurrentIrp;
+
+        Status = HalAllocateAdapterChannel(AdapterObject,
+                                           &ScatterGatherContext->Wcb,
+                                           NumberOfMapRegisters,
+                                           HalpScatterGatherAdapterControl);
+
+        if (!NT_SUCCESS(Status))
+        {
+            if (!UsingUserBuffer)
+                ExFreePoolWithTag(ScatterGatherBuffer, TAG_DMA);
+            return Status;
+        }
+    }
+
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS