[HAL]
[reactos.git] / reactos / hal / halx86 / generic / dma.c
index 29b822a..dcf9d14 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id$
+/*
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -72,6 +72,8 @@
 /* INCLUDES *****************************************************************/
 
 #include <hal.h>
+#include <suppress.h>
+
 #define NDEBUG
 #include <debug.h>
 
@@ -221,8 +223,16 @@ HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject,
     KIRQL OldIrql;
     ULONG MapRegisterCount;
 
-    /* FIXME: Check if enough map register slots are available. */
+    /* Check if enough map register slots are available. */
     MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers);
+    if (MapRegisterCount + AdapterObject->NumberOfMapRegisters > MAX_MAP_REGISTERS)
+    {
+        DPRINT("No more map register slots available! (Current: %d | Requested: %d | Limit: %d)\n",
+               AdapterObject->NumberOfMapRegisters,
+               MapRegisterCount,
+               MAX_MAP_REGISTERS);
+        return FALSE;
+    }
 
     /*
      * Allocate memory for the new map registers. For 32-bit adapters we use
@@ -301,7 +311,7 @@ HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject,
             }
 
             RtlClearBit(AdapterObject->MapRegisters,
-                        CurrentEntry - AdapterObject->MapRegisterBase);
+                        (ULONG)(CurrentEntry - AdapterObject->MapRegisterBase));
             CurrentEntry->VirtualAddress = VirtualAddress;
             CurrentEntry->PhysicalAddress = PhysicalAddress;
 
@@ -544,8 +554,9 @@ HalpDmaInitializeEisaAdapter(IN PADAPTER_OBJECT AdapterObject,
         if (Controller == 1)
         {
             /* Set the Request Data */
+            _PRAGMA_WARNING_SUPPRESS(__WARNING_DEREF_NULL_PTR)
             WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
-            
+
             /* Unmask DMA Channel */
             WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask,
                              AdapterObject->ChannelNumber | DMA_CLEARMASK);
@@ -554,7 +565,7 @@ HalpDmaInitializeEisaAdapter(IN PADAPTER_OBJECT AdapterObject,
         {
             /* Set the Request Data */
             WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
-            
+
             /* Unmask DMA Channel */
             WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask,
                              AdapterObject->ChannelNumber | DMA_CLEARMASK);
@@ -599,7 +610,6 @@ HalGetAdapter(IN PDEVICE_DESCRIPTION DeviceDescription,
               OUT PULONG NumberOfMapRegisters)
 {
     PADAPTER_OBJECT AdapterObject = NULL;
-    PADAPTER_OBJECT MasterAdapter;
     BOOLEAN EisaAdapter;
     ULONG MapRegisters;
     ULONG MaximumLength;
@@ -614,9 +624,12 @@ HalGetAdapter(IN PDEVICE_DESCRIPTION DeviceDescription,
      * Also note that we check for channel number since there are only 8 DMA
      * channels on ISA, so any request above this requires new adapter.
      */
-    if ((DeviceDescription->InterfaceType == Isa) || !(DeviceDescription->Master))
+    if (((DeviceDescription->InterfaceType == Eisa) ||
+         (DeviceDescription->InterfaceType == Isa)) || !(DeviceDescription->Master))
     {
-        if ((DeviceDescription->InterfaceType == Isa) && (DeviceDescription->DmaChannel >= 8))
+        if (((DeviceDescription->InterfaceType == Isa) ||
+             (DeviceDescription->InterfaceType == Eisa)) &&
+            (DeviceDescription->DmaChannel >= 8))
         {
             EisaAdapter = FALSE;
         }
@@ -708,21 +721,7 @@ HalGetAdapter(IN PDEVICE_DESCRIPTION DeviceDescription,
         if (MapRegisters > 0)
         {
             AdapterObject->NeedsMapRegisters = TRUE;
-            MasterAdapter = HalpMasterAdapter;
             AdapterObject->MapRegistersPerChannel = MapRegisters;
-
-            /*
-             * FIXME: Verify that the following makes sense. Actually
-             * MasterAdapter->NumberOfMapRegisters contains even the number
-             * of gaps, so this will not work correctly all the time. It
-             * doesn't matter much since it's only optimization to avoid
-             * queuing work items in HalAllocateAdapterChannel.
-             */
-            MasterAdapter->CommittedMapRegisters += MapRegisters;
-            if (MasterAdapter->CommittedMapRegisters > MasterAdapter->NumberOfMapRegisters)
-            {
-                HalpGrowMapBuffers(MasterAdapter, 0x10000);
-            }
         }
         else
         {
@@ -921,7 +920,7 @@ typedef struct _SCATTER_GATHER_CONTEXT {
        ULONG MapRegisterCount;
        BOOLEAN WriteToDevice;
 } SCATTER_GATHER_CONTEXT, *PSCATTER_GATHER_CONTEXT;
-       
+
 
 IO_ALLOCATION_ACTION
 NTAPI
@@ -936,10 +935,10 @@ HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
        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;
@@ -952,16 +951,16 @@ HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
                                                                                                                   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");
@@ -978,14 +977,14 @@ HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
        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;
 }
 
@@ -1029,10 +1028,10 @@ HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
                                                 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;
@@ -1041,7 +1040,7 @@ HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
        AdapterControlContext->AdapterListControlRoutine = ExecutionRoutine;
        AdapterControlContext->AdapterListControlContext = Context;
        AdapterControlContext->WriteToDevice = WriteToDevice;
-       
+
        return IoAllocateAdapterChannel(AdapterObject,
                                        DeviceObject,
                                                                        AdapterControlContext->MapRegisterCount,
@@ -1075,7 +1074,7 @@ HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
 {
     PSCATTER_GATHER_CONTEXT AdapterControlContext = (PSCATTER_GATHER_CONTEXT)ScatterGather->Reserved;
        ULONG i;
-       
+
        for (i = 0; i < ScatterGather->NumberOfElements; i++)
        {
             IoFlushAdapterBuffers(AdapterObject,
@@ -1090,9 +1089,9 @@ HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
        IoFreeMapRegisters(AdapterObject,
                           AdapterControlContext->MapRegisterBase,
                                           AdapterControlContext->MapRegisterCount);
-                                          
+
        DPRINT("S/G DMA has finished!\n");
-       
+
        ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
        ExFreePoolWithTag(ScatterGather, TAG_DMA);
 }
@@ -1145,10 +1144,10 @@ HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject)
         do
         {
             OldCount = Count;
-         
+
             /* Send Reset */
             WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
-            
+
             /* Read Count */
             Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
                                     [AdapterObject->ChannelNumber].DmaBaseCount);
@@ -1164,10 +1163,10 @@ HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject)
         do
         {
             OldCount = Count;
-         
+
             /* Send Reset */
             WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
-            
+
             /* Read Count */
             Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
                                     [AdapterObject->ChannelNumber].DmaBaseCount);
@@ -1208,7 +1207,7 @@ HalpGrowMapBufferWorker(IN PVOID DeferredContext)
      */
     KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, FALSE, NULL);
     Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter,
-                                   WorkItem->NumberOfMapRegisters);
+                                   WorkItem->NumberOfMapRegisters << PAGE_SHIFT);
     KeSetEvent(&HalpDmaLock, 0, 0);
 
     if (Succeeded)
@@ -1330,24 +1329,19 @@ HalAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject,
 
         if (Index == MAXULONG)
         {
+            InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
+
             WorkItem = ExAllocatePoolWithTag(NonPagedPool,
                                              sizeof(GROW_WORK_ITEM),
                                              TAG_DMA);
-            if (!WorkItem)
+            if (WorkItem)
             {
-                KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
-                AdapterObject->NumberOfMapRegisters = 0;
-                IoFreeAdapterChannel(AdapterObject);
-                return STATUS_INSUFFICIENT_RESOURCES;
-            }
-
-            InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
-
-            ExInitializeWorkItem(&WorkItem->WorkQueueItem, HalpGrowMapBufferWorker, WorkItem);
-            WorkItem->AdapterObject = AdapterObject;
-            WorkItem->NumberOfMapRegisters = NumberOfMapRegisters;
+                ExInitializeWorkItem(&WorkItem->WorkQueueItem, HalpGrowMapBufferWorker, WorkItem);
+                WorkItem->AdapterObject = AdapterObject;
+                WorkItem->NumberOfMapRegisters = NumberOfMapRegisters;
 
-            ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue);
+                ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue);
+            }
 
             KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
 
@@ -1448,7 +1442,7 @@ IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
 
         DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
         if (!DeviceQueueEntry) break;
-      
+
         WaitContextBlock = CONTAINING_RECORD(DeviceQueueEntry,
                                              WAIT_CONTEXT_BLOCK,
                                              WaitQueueEntry);
@@ -1556,7 +1550,7 @@ IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject,
 
         RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
         RtlClearBits(MasterAdapter->MapRegisters,
-                     RealMapRegisterBase - MasterAdapter->MapRegisterBase,
+                     (ULONG)(RealMapRegisterBase - MasterAdapter->MapRegisterBase),
                      NumberOfMapRegisters);
     }
 
@@ -1571,7 +1565,7 @@ IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject,
 
         Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
                                        AdapterObject->NumberOfMapRegisters,
-                                       MasterAdapter->NumberOfMapRegisters);
+                                       0);
         if (Index == MAXULONG)
         {
             InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
@@ -1602,12 +1596,12 @@ IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject,
                 {
                     KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
                     RtlClearBits(MasterAdapter->MapRegisters,
-                                 AdapterObject->MapRegisterBase -
-                                 MasterAdapter->MapRegisterBase,
+                                 (ULONG)(AdapterObject->MapRegisterBase -
+                                         MasterAdapter->MapRegisterBase),
                                  AdapterObject->NumberOfMapRegisters);
                     KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
                 }
-            
+
                 IoFreeAdapterChannel(AdapterObject);
                 break;
 
@@ -2020,16 +2014,16 @@ IoMapTransfer(IN PADAPTER_OBJECT AdapterObject,
 
             /* Reset Register */
             WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
-         
+
             /* Set the Mode */
             WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte);
-         
+
             /* Set the Offset Register */
             WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
                              (UCHAR)(TransferOffset));
             WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
                              (UCHAR)(TransferOffset >> 8));
-                          
+
             /* Set the Page Register */
             WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
                              (UCHAR)(PhysicalAddress.LowPart >> 16));
@@ -2038,13 +2032,13 @@ IoMapTransfer(IN PADAPTER_OBJECT AdapterObject,
                 WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
                                  0);
             }
-         
+
             /* Set the Length */
             WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
                              (UCHAR)(TransferLength - 1));
             WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
                              (UCHAR)((TransferLength - 1) >> 8));
-                          
+
             /* Unmask the Channel */
             WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
         }
@@ -2054,16 +2048,16 @@ IoMapTransfer(IN PADAPTER_OBJECT AdapterObject,
 
             /* Reset Register */
             WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
-         
+
             /* Set the Mode */
             WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte);
-         
+
             /* Set the Offset Register */
             WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
                              (UCHAR)(TransferOffset));
             WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
                              (UCHAR)(TransferOffset >> 8));
-                          
+
             /* Set the Page Register */
             WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
                              (UCHAR)(PhysicalAddress.u.LowPart >> 16));
@@ -2072,13 +2066,13 @@ IoMapTransfer(IN PADAPTER_OBJECT AdapterObject,
                 WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
                                  0);
             }
-         
+
             /* Set the Length */
             WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
                              (UCHAR)(TransferLength - 1));
             WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
                              (UCHAR)((TransferLength - 1) >> 8));
-                          
+
             /* Unmask the Channel */
             WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
                              AdapterObject->ChannelNumber | DMA_CLEARMASK);