Complete reimplementation of HAL DMA routines.
authorFilip Navara <filip.navara@gmail.com>
Mon, 22 Aug 2005 08:39:42 +0000 (08:39 +0000)
committerFilip Navara <filip.navara@gmail.com>
Mon, 22 Aug 2005 08:39:42 +0000 (08:39 +0000)
The key changes are
* Proper support for bus-master device adapters.
* Real implementation of map registers.
* Basic support for emulating scatter/gather DMA on
  devices that don't support it in hardware.
* Support for transfers that aren't page aligned.
* Proper detection and support of EISA DMA controllers.
* Fixed prototype for HalFlushCommonBuffer.

svn path=/trunk/; revision=17470

reactos/hal/hal/hal.c
reactos/hal/hal/hal.def
reactos/hal/halx86/generic/adapter.c [deleted file]
reactos/hal/halx86/generic/dma.c
reactos/hal/halx86/generic/generic.xml
reactos/hal/halx86/include/hal.h
reactos/hal/halx86/include/haldma.h [new file with mode: 0644]
reactos/hal/halx86/include/halp.h

index c031a64..f0c5173 100644 (file)
@@ -211,10 +211,7 @@ HalFlushCommonBuffer(
   ULONG Unknown2,
   ULONG Unknown3,
   ULONG Unknown4,
-  ULONG Unknown5,
-  ULONG Unknown6,
-  ULONG Unknown7,
-  ULONG Unknown8)
+  ULONG Unknown5)
 {
   UNIMPLEMENTED;
 
index 9f9d7fd..3b38a26 100644 (file)
@@ -20,7 +20,7 @@ HalDisableSystemInterrupt@8
 HalDisplayString@4
 HalEnableSystemInterrupt@12
 HalEndSystemInterrupt@8
-HalFlushCommonBuffer@32
+HalFlushCommonBuffer@20
 HalFreeCommonBuffer@24
 HalGetAdapter@8
 HalGetBusData@20
diff --git a/reactos/hal/halx86/generic/adapter.c b/reactos/hal/halx86/generic/adapter.c
deleted file mode 100644 (file)
index 135d2da..0000000
+++ /dev/null
@@ -1,717 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            hal/x86/adapter.c (from ntoskrnl/io/adapter.c)
- * PURPOSE:         DMA handling
- * PROGRAMMERS:     David Welch (welch@mcmail.com)
- *                  Vizzini (vizzini@plasmic.com)
- * UPDATE HISTORY:
- *                  Created 22/05/98
- *                  18-Oct-2003 Vizzini DMA support modifications
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <hal.h>
-#define NDEBUG
-#include <debug.h>
-
-/* FUNCTIONS *****************************************************************/
-
-/* NOTE: IoAllocateAdapterChannel in NTOSKRNL.EXE */
-
-\f
-NTSTATUS STDCALL
-HalAllocateAdapterChannel(
-  PADAPTER_OBJECT AdapterObject,
-  PWAIT_CONTEXT_BLOCK WaitContextBlock,
-  ULONG NumberOfMapRegisters,
-  PDRIVER_CONTROL ExecutionRoutine)
-/*
- * FUNCTION: Sets up an ADAPTER_OBJECT with map registers
- * ARGUMENTS:
- *     - AdapterObject: pointer to an ADAPTER_OBJECT to set up 
- *     - WaitContextBlock: Context block to be used with ExecutionRoutine
- *     - NumberOfMapRegisters: number of map registers requested 
- *     - ExecutionRoutine: callback to call when map registers are allocated
- * RETURNS:
- *     STATUS_INSUFFICIENT_RESOURCES if map registers cannot be allocated
- *     STATUS_SUCCESS in all other cases, including if the callbacak had
- *                    to be queued for later delivery
- * NOTES:
- *     - the ADAPTER_OBJECT struct is undocumented; please make copious
- *       notes in hal.h if anything is changed or improved since there is
- *       no other documentation for this data structure
- * BUGS:
- *     - it's possible that some of this code is in the wrong place
- *     - there are many unhandled cases
- */
-{
-  LARGE_INTEGER MinAddress;
-  LARGE_INTEGER MaxAddress;
-  LARGE_INTEGER BoundryAddressMultiple;
-  IO_ALLOCATION_ACTION Retval;
-  
-  ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
-  
-  /*
-  FIXME: return STATUS_INSUFFICIENT_RESOURCES if the NumberOfMapRegisters 
-  requested is larger than the value returned by IoGetDmaAdapter. 
-  */
-
-  /* set up the wait context block in case we can't run right away */
-  WaitContextBlock->DeviceRoutine = ExecutionRoutine;
-  WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
-
-  /* returns true if queued, else returns false and sets the queue to busy */
-  if(KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue, &WaitContextBlock->WaitQueueEntry))
-    return STATUS_SUCCESS;
-
-  /* why 64K alignment? */
-  /*
-   * X86 lacks map registers, so for now, we allocate a contiguous
-   * block of physical memory <16MB and copy all DMA buffers into
-   * that.  This can be optimized.
-   *
-   * FIXME: We propably shouldn't allocate the memory here for common
-   * buffer transfers. See a comment in IoMapTransfer about common buffer
-   * support.
-   */
-  
-  MinAddress.QuadPart = 0;
-  BoundryAddressMultiple.QuadPart = 0;
-  if ((AdapterObject->Dma64BitAddresses) && (AdapterObject->MasterDevice)) 
-    {
-      MaxAddress.QuadPart = 0xFFFFFFFFFFFFFFFFLL; /* 64Bit: >4GB address range */
-    } 
-  else if ((AdapterObject->Dma32BitAddresses) && (AdapterObject->MasterDevice)) 
-    {
-      MaxAddress.QuadPart = 0xFFFFFFFF; /* 32Bit: 4GB address range */
-    } 
-  else 
-    {
-      MaxAddress.QuadPart = 0x00FFFFFF; /* 24Bit: 16MB address range */
-      if (AdapterObject->Width16Bits)
-        {
-          BoundryAddressMultiple.QuadPart = 0x20000;  /* 128k boundary */
-        }
-      else
-        {
-          BoundryAddressMultiple.QuadPart = 0x10000;  /* 64k boundary */
-        }
-    }
-  AdapterObject->MapRegisterBase = MmAllocateContiguousMemorySpecifyCache(
-      NumberOfMapRegisters * PAGE_SIZE,
-      MinAddress,
-      MaxAddress,
-      BoundryAddressMultiple,
-      MmCached);
-
-  if(!AdapterObject->MapRegisterBase)
-    return STATUS_INSUFFICIENT_RESOURCES;
-
-  AdapterObject->CommittedMapRegisters = NumberOfMapRegisters;
-
-  /* call the client's AdapterControl callback with its map registers and context */
-  Retval = ExecutionRoutine(WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp, 
-      AdapterObject->MapRegisterBase, WaitContextBlock->DeviceContext);
-
-  /* 
-   * KeepObject: don't free any resources; the ADAPTER_OBJECT is still in use
-   *             and the caller will call IoFreeAdapterChannel later
-   *
-   * DeallocateObject: Deallocate the map registers and release the ADAPTER_OBJECT
-   *             so someone else can use it
-   *
-   * DeallocateObjectKeepRegisters: release the ADAPTER_OBJECT but hang on to
-   *             the map registers.  The client will later call IoFreeMapRegisters.
-   *
-   * NOTE - IoFreeAdapterChannel runs the queue, so it must be called
-   *        unless the adapter object is not to be freed.
-   */
-  if( Retval == DeallocateObject )
-      IoFreeAdapterChannel(AdapterObject);
-  else if(Retval == DeallocateObjectKeepRegisters)
-    {
-      /* don't free the allocated map registers - this is what IoFreeAdapterChannel checks */
-      AdapterObject->CommittedMapRegisters = 0;
-      IoFreeAdapterChannel(AdapterObject);
-    }
-
-  /*
-   * if we don't call IoFreeAdapterChannel, the next device won't get de-queued,
-   * which is what we want.
-   */
-
-  return STATUS_SUCCESS;
-}
-
-
-BOOLEAN
-HalpGrowMapBuffers(
-  IN PADAPTER_OBJECT   AdapterObject,
-  IN ULONG             SizeOfMapBuffers)
-/*
- * FUNCTION: Allocate initial, or additional, map buffers for IO adapters.
- * ARGUMENTS:
- *     AdapterObject: DMA adapter to allocate buffers for.
- *     SizeOfMapBuffers: Size of the map buffers to allocate
- * NOTES:
- *     - Needs to be tested...
- */
-{
-       //ULONG PagesToAllocate = BYTES_TO_PAGES(SizeOfMapBuffers);
-       
-       /* TODO: Allocation */
-
-       return TRUE;
-}
-
-PADAPTER_OBJECT STDCALL
-HalpAllocateAdapterEx(
-  ULONG NumberOfMapRegisters,
-  BOOLEAN IsMaster,
-  BOOLEAN Dma32BitAddresses)
-/*
- * FUNCTION: Allocates an ADAPTER_OBJECT, optionally creates the Master Adapter.
- * ARGUMENTS:
- *     - NumberOfMapRegisters: Number of map registers to allocate
- *     - IsMaster: Wether this is a Master Device or not
- *     - Dma32BitAddresses: Wether 32-bit Addresses are supported
- * RETURNS:
- *     - Pointer to Adapter Object, or NULL if failure.
- * BUGS:
- *     - Some stuff is unhandled/incomplete
- */
-{
-       OBJECT_ATTRIBUTES ObjectAttributes;
-       ULONG ObjectSize;
-       ULONG BitmapSize;
-       NTSTATUS Status;
-       ULONG AllowedMapRegisters = 64;
-       PADAPTER_OBJECT AdapterObject;
-       HANDLE Handle;
-       
-       /* Allocate the Master Adapter if we haven't already 
-          but make sure we're not asked to do it now, and also check if we need it */
-       if ((MasterAdapter == NULL) && (!IsMaster) && (NumberOfMapRegisters)) {
-               
-               /* Allocate and Save */
-               DPRINT("Allocating the Master Adapter Object\n");
-               MasterAdapter = HalpAllocateAdapterEx(NumberOfMapRegisters,
-                                                    TRUE,
-                                                    Dma32BitAddresses);
-               
-               /* Cancel on Failure */
-               DPRINT("Checking if Master Adapter was allocated properly\n");
-               if (!MasterAdapter) return NULL;
-       }
-       
-       /* Initialize the Object Attributes for the Adapter Object */
-       InitializeObjectAttributes(&ObjectAttributes,
-                                  NULL,
-                                  OBJ_PERMANENT,
-                                  NULL,
-                                  NULL);
-       
-       /* Check if this is the Master Adapter, in which case we need to allocate the bitmap */
-       if (IsMaster) {
-               /* Size due to the Bitmap + Bytes in the Bitmap Buffer (8 bytes, 64 bits)*/
-               BitmapSize = sizeof(RTL_BITMAP) + (AllowedMapRegisters + 7) / 8;
-               
-               /* We will put the Bitmap Buffer after the Adapter Object for simplicity */
-               ObjectSize = sizeof(ADAPTER_OBJECT) + BitmapSize;
-       } else {
-               ObjectSize = sizeof(ADAPTER_OBJECT);
-       }
-       
-       /* Create and Allocate the Object */
-       DPRINT("Creating the Object\n");
-       Status = ObCreateObject(KernelMode,
-                               IoAdapterObjectType,
-                               &ObjectAttributes,
-                               KernelMode,
-                               NULL,
-                               ObjectSize,
-                               0,
-                               0,
-                               (PVOID)&AdapterObject);
-       
-       if (!NT_SUCCESS(Status)) return NULL;
-       
-       /* Add a Reference */
-       DPRINT("Referencing the Object\n");
-       Status = ObReferenceObjectByPointer(AdapterObject,
-                                           FILE_READ_DATA | FILE_WRITE_DATA,
-                                           IoAdapterObjectType,
-                                           KernelMode);
-       
-       if (!NT_SUCCESS(Status)) return NULL;
-       
-       /* It's a Valid Object, so now we can play with the memory */
-       RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
-       
-       /* Insert it into the Object Table */
-       DPRINT("Inserting the Object\n");
-       Status = ObInsertObject(AdapterObject,
-                               NULL,
-                               FILE_READ_DATA | FILE_WRITE_DATA,
-                               0,
-                               NULL,
-                               &Handle);
-       
-       if (!NT_SUCCESS(Status)) return NULL;
-       
-       /* We don't want the handle */
-       NtClose(Handle);        
-       
-       /* Set up the Adapter Object fields */
-       AdapterObject->MapRegistersPerChannel = 1;
-       
-       /* Set the Master if needed (master only needed if we use Map Registers) */
-       if (NumberOfMapRegisters) AdapterObject->MasterAdapter = MasterAdapter;
-       
-       /* Initalize the Channel Wait queue, which every adapter has */
-       DPRINT("Initializing the Device Queue of the Object\n");
-       KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
-       
-       /* Initialize the SpinLock, Queue and Bitmap, which are kept in the Master Adapter only */
-       if (IsMaster) {
-               
-               DPRINT("Initializing the Master Adapter Stuff\n");
-               KeInitializeSpinLock(&AdapterObject->SpinLock);
-               InitializeListHead(&AdapterObject->AdapterQueue);
-               
-               /* As said previously, we put them here for simplicity */
-               AdapterObject->MapRegisters = (PVOID)(AdapterObject + 1);
-               
-               /* Set up Bitmap */
-               RtlInitializeBitMap(AdapterObject->MapRegisters,
-                                   (PULONG)(AdapterObject->MapRegisters + 1),
-                                   AllowedMapRegisters);
-                                   
-               /* Reset the Bitmap */  
-               RtlSetAllBits(AdapterObject->MapRegisters);
-               AdapterObject->NumberOfMapRegisters = 0;
-               AdapterObject->CommittedMapRegisters = 0;
-               
-               /* Allocate Memory for the Map Registers */
-               AdapterObject->MapRegisterBase = ExAllocatePool(NonPagedPool,
-                                                               AllowedMapRegisters * sizeof(DWORD));
-               
-               /* Clear them */
-               RtlZeroMemory(AdapterObject->MapRegisterBase, AllowedMapRegisters * sizeof(DWORD));
-               
-               /* Allocate the contigous memory */
-               DPRINT("Allocating Buffers\n");
-               HalpGrowMapBuffers(AdapterObject, 0x1000000);
-       }
-       
-       DPRINT("Adapter Object allocated\n");
-       return AdapterObject;   
-}
-
-\f
-BOOLEAN STDCALL
-IoFlushAdapterBuffers (
-  PADAPTER_OBJECT      AdapterObject,
-  PMDL         Mdl,
-  PVOID                MapRegisterBase,
-  PVOID                CurrentVa,
-  ULONG                Length,
-  BOOLEAN              WriteToDevice)
-/*
- * FUNCTION: flush any data remaining in the dma controller's memory into the host memory
- * ARGUMENTS:
- *     AdapterObject: the adapter object to flush
- *     Mdl: original MDL to flush data into
- *     MapRegisterBase: map register base that was just used by IoMapTransfer, etc
- *     CurrentVa: offset into Mdl to be flushed into, same as was passed to IoMapTransfer
- *     Length: length of the buffer to be flushed into
- *     WriteToDevice: True if it's a write, False if it's a read
- * RETURNS:
- *     TRUE in all cases
- * NOTES:
- *     - This copies data from the map register-backed buffer to the user's target buffer.
- *       Data is not in the user buffer until this is called.
- *     - This is only meaningful on a read operation.  Return immediately for a write.
- */
-{
-  ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
-  
-  /* this can happen if the card supports scatter/gather */
-  if(!MapRegisterBase)
-    return TRUE;
-
-  /* mask out (disable) the dma channel */
-  if (AdapterObject->AdapterNumber == 1) {
-  
-               /* Set this for Ease */
-               PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
-       
-               /* Set Channel */
-               WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_SETMASK);
-  } else {
-               /* Set this for Ease */
-               PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
-       
-               /* Set Channel */
-               WRITE_PORT_UCHAR(&DmaControl2->SingleMask, (AdapterObject->ChannelNumber - 4) | DMA_SETMASK);
-  }
-  
-  if(WriteToDevice)
-    return TRUE;
-    
-  memcpy( 
-        (PVOID)((DWORD)MmGetSystemAddressForMdl( Mdl ) + (DWORD)CurrentVa - (DWORD)MmGetMdlVirtualAddress( Mdl )), 
-      MapRegisterBase, Length );
-
-  return TRUE;
-}
-
-\f
-VOID STDCALL
-IoFreeAdapterChannel (PADAPTER_OBJECT  AdapterObject)
-/*
- * FUNCTION: frees DMA resources allocated by IoAllocateAdapterChannel
- * ARGUMENTS:
- *     AdapterObject: Adapter object with resources to free
- * NOTES:
- *     - This function releases the DMA adapter and optionally the map registers
- *     - After releasing the adapter, it checks the adapter's queue and runs
- *       each queued device object in series until the queue is empty
- *     - This is the only way the device queue is emptied.
- */
-{
-  LARGE_INTEGER MaxAddress;
-  LARGE_INTEGER MinAddress;
-  LARGE_INTEGER BoundryAddressMultiple;
-  PWAIT_CONTEXT_BLOCK WaitContextBlock;
-  IO_ALLOCATION_ACTION Retval;
-
-  while(1)
-    {
-      /* To keep map registers, call here with the following set to 0 */
-      if(AdapterObject->CommittedMapRegisters)
-        IoFreeMapRegisters(AdapterObject, AdapterObject->MapRegisterBase, AdapterObject->CommittedMapRegisters);
-
-      if(!(WaitContextBlock = (PWAIT_CONTEXT_BLOCK)KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue)))
-        break;
-
-      /*
-       * the following should really be done elsewhere since this
-       * function really can't return an error code.  FIXME.
-       */
-
-      MinAddress.QuadPart = 0;
-      BoundryAddressMultiple.QuadPart = 0;
-      if ((AdapterObject->Dma64BitAddresses) && (AdapterObject->MasterDevice)) 
-        {
-          MaxAddress.QuadPart = 0xFFFFFFFFFFFFFFFFLL; /* 64Bit: >4GB address range */
-        } 
-      else if ((AdapterObject->Dma32BitAddresses) && (AdapterObject->MasterDevice)) 
-        {
-          MaxAddress.QuadPart = 0xFFFFFFFF; /* 32Bit: 4GB address range */
-        } 
-      else 
-        {
-          MaxAddress.QuadPart = 0x00FFFFFF; /* 24Bit: 16MB address range */
-          if (AdapterObject->Width16Bits)
-            {
-              BoundryAddressMultiple.QuadPart = 0x20000;  /* 128k boundary */
-            }
-          else
-            {
-              BoundryAddressMultiple.QuadPart = 0x10000;  /* 64k boundary */
-            }
-        }
-
-      AdapterObject->MapRegisterBase = MmAllocateContiguousMemorySpecifyCache( 
-          WaitContextBlock->NumberOfMapRegisters * PAGE_SIZE,
-          MinAddress,
-          MaxAddress,
-          BoundryAddressMultiple,
-          MmCached);
-
-      if(!AdapterObject->MapRegisterBase)
-        return;
-
-      /* call the adapter control routine */
-      Retval = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp,
-          AdapterObject->MapRegisterBase, WaitContextBlock->DeviceContext);
-
-      if(Retval == KeepObject)
-        {
-          /* we're done until the caller manually calls IoFreeAdapterChannel */
-          break;
-        }
-      else if(Retval == DeallocateObjectKeepRegisters)
-        {
-          /* hide the map registers so they aren't deallocated next time around */
-          AdapterObject->CommittedMapRegisters = 0;
-        }
-    }
-}
-
-\f
-VOID STDCALL
-IoFreeMapRegisters (
-  IN PADAPTER_OBJECT   AdapterObject,
-  IN PVOID             MapRegisterBase,
-  IN ULONG             NumberOfMapRegisters)
-/*
- * FUNCTION: free map registers reserved by the system for a DMA
- * ARGUMENTS:
- *     AdapterObject: dma adapter to free map registers on
- *     MapRegisterBase: hadle to map registers to free
- *     NumberOfRegisters: number of map registers to be freed
- * NOTES:
- *     - XXX real windows has a funky interdependence between IoFreeMapRegisters 
- *       and IoFreeAdapterChannel 
- * BUGS:
- *     - needs to be improved to use a real map register implementation
- */
-{
-  if( AdapterObject->CommittedMapRegisters )
-    {
-      MmFreeContiguousMemory(AdapterObject->MapRegisterBase);
-      AdapterObject->MapRegisterBase = 0;
-    }
-}
-
-\f
-PHYSICAL_ADDRESS  STDCALL
-IoMapTransfer (
-  IN PADAPTER_OBJECT   AdapterObject,
-  IN PMDL              Mdl,
-  IN PVOID             MapRegisterBase,
-  IN PVOID             CurrentVa,
-  IN OUT PULONG                Length,
-  IN BOOLEAN           WriteToDevice)
-/*
- * FUNCTION: map a dma for transfer and do the dma if it's a slave
- * ARGUMENTS:
- *     AdapterObject: adapter object to do the dma on. busmaster may pass NULL.
- *     Mdl: locked-down user buffer to DMA in to or out of
- *     MapRegisterBase: handle to map registers to use for this dma. allways NULL
- *      when doing s/g.
- *     CurrentVa: index into Mdl to transfer into/out of
- *     Length: length of transfer in/out. Only modified on out when doing s/g.
- *     WriteToDevice: TRUE if it's an output dma, FALSE otherwise
- * RETURNS: 
- *     If a busmaster: A logical address that can be used to program a dma controller
- *     Otherwise: nothing meaningful
- * NOTES:
- *     - This function does a copyover to contiguous memory <16MB
- *     - If it's a slave transfer, this function actually performs it.
- * BUGS:
- *     - If the controller supports scatter/gather, the copyover should not happen
- */
-{
-  PHYSICAL_ADDRESS Address;
-  KIRQL OldIrql;
-  ULONG LengthShift = 0;
-
-  Address.QuadPart = 0;
-
-  /* Isa System (slave) DMA? */
-  if (MapRegisterBase && !AdapterObject->MasterDevice)
-  {
-    KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql);
-
-    /*
-     * FIXME: Handle case when doing common-buffer System DMA. In this case,
-     * the buffer described by MDL is already phys. contiguous and below
-     * 16 mega. Driver makes a one-shot call to IoMapTransfer during init.
-     * to program controller with the common-buffer.
-     *
-     * UPDATE: Common buffer support is in place, but it's not done in a
-     * clean way. We use the buffer passed by the MDL in case that the
-     * adapter object is marked as auto initialize. I'm not sure if this
-     * is correct and if not, how to do it properly. Note that it's also
-     * possible to allocate the common buffer with different adapter object
-     * and IoMapTransfer must still work in this case. Eventually this should
-     * be cleaned up somehow or at least this comment modified to reflect
-     * the reality.
-     * -- Filip Navara, 19/07/2004     
-     */
-
-    /* if it is a write to the device, copy the caller buffer to the low buffer */
-    if (WriteToDevice && !AdapterObject->AdapterMode.AutoInitialize)
-    {
-      memcpy(MapRegisterBase,
-             (char*)MmGetSystemAddressForMdl(Mdl) + ((ULONG)CurrentVa - (ULONG)MmGetMdlVirtualAddress(Mdl)),
-                  *Length );
-    }
-
-    /* Writer Adapter Mode, transfer type */
-    AdapterObject->AdapterMode.TransferType = (WriteToDevice ? WRITE_TRANSFER : READ_TRANSFER);
-
-    /* program up the dma controller, and return */
-    if (!AdapterObject->AdapterMode.AutoInitialize) {
-      Address = MmGetPhysicalAddress( MapRegisterBase );
-    } else {
-      Address = MmGetPhysicalAddress( CurrentVa );
-    }
-    
-    /* 16-bit DMA has a shifted length */
-    if (AdapterObject->Width16Bits) {
-      LengthShift = 1;
-    }
-     
-    /* Make the Transfer */
-    if (AdapterObject->AdapterNumber == 1) {
-    
-       PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; /* For Writing Less Code */
-       
-       /* Mask the Channel */
-       WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_SETMASK);
-
-       /* Reset Register */
-       WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
-       
-       /* Set the Mode */
-       WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterObject->AdapterModeByte);
-       
-       /* Set the Page Register */
-       WRITE_PORT_UCHAR(AdapterObject->PagePort, (UCHAR)(Address.u.LowPart >> 16));
-
-       /* Set the Offset Register (apparently always 0 for us if I trust the previous comment) */
-       WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0);
-       WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0);
-       
-       /* Set the Length */
-       WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
-                       (UCHAR)((*Length >> LengthShift) - 1));
-       WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
-                       (UCHAR)(((*Length >> LengthShift) - 1) >> 8));
-                       
-       /* Unmask the Channel */
-       WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
-    } else {
-        PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; /* For Writing Less Code */
-       
-       /* Mask the Channel */
-       WRITE_PORT_UCHAR(&DmaControl2->SingleMask, AdapterObject->ChannelNumber | DMA_SETMASK);
-
-       /* Reset Register */
-       WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
-       
-       /* Set the Mode */
-       WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterObject->AdapterModeByte);
-       
-       /* Set the Page Register */
-       WRITE_PORT_UCHAR(AdapterObject->PagePort, (UCHAR)(Address.u.LowPart >> 16));
-
-       /* Set the Offset Register (apparently always 0 for us if I trust the previous comment) */
-       WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0);
-       WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0);
-       
-       /* Set the Length */
-       WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
-                       (UCHAR)((*Length >> LengthShift) - 1));
-       WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
-                       (UCHAR)(((*Length >> LengthShift) - 1) >> 8));
-                       
-       /* Unmask the Channel */
-       WRITE_PORT_UCHAR(&DmaControl2->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
-    }
-       
-    /* Release Spinlock */
-    KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
-
-    /* 
-    NOTE: Return value should be ignored when doing System DMA.
-    Maybe return some more obvious invalid address here (thou returning 
-    MapRegisterBase is also wrong;-)to catch invalid use?
-    */
-    Address.QuadPart = (ULONG)MapRegisterBase;
-    return Address;
-  }
-  
-
-  /* 
-  Busmaster with s/g support?   
-  NOTE: old docs allowed busmasters to pass a NULL Adapter. In this case, MapRegisterBase 
-  being NULL is used to detect a s/g busmaster.
-  */
-  if ((!AdapterObject && !MapRegisterBase) ||
-      (AdapterObject && AdapterObject->MasterDevice && AdapterObject->ScatterGather))
-  {
-    /* 
-    Just return the passed VA's corresponding phys. address. 
-    Update length to the number of phys. contiguous bytes found.
-    */
-  
-    PULONG MdlPages;
-    ULONG MdlPageIndex, PhysContiguousLen;
-    ULONG PhysAddress;
-    
-    MdlPages = (PULONG)(Mdl + 1);
-    
-    /* Get VA's corresponding mdl phys. page index */
-    MdlPageIndex = ((ULONG)CurrentVa - (ULONG)Mdl->StartVa) / PAGE_SIZE;
-   
-    /* Get phys. page containing the VA */
-    PhysAddress = MdlPages[MdlPageIndex];
-    
-    PhysContiguousLen = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
-    
-    /* VA to map may span several contiguous phys. pages (unlikely) */
-    while (PhysContiguousLen < *Length &&
-           MdlPages[MdlPageIndex++] + PAGE_SIZE == MdlPages[MdlPageIndex])
-    {
-      /* 
-      Note that allways adding PAGE_SIZE may make PhysContiguousLen greater
-      than Length if buffer doesn't end on page boundary. Take this
-      into consideration below. 
-      */
-      PhysContiguousLen += PAGE_SIZE; 
-    }
-    
-    if (PhysContiguousLen < *Length)
-    {
-      *Length = PhysContiguousLen;
-    }
-    
-    //add offset to phys. page address
-    Address.QuadPart = PhysAddress + BYTE_OFFSET(CurrentVa);
-    return Address;
-  }
-  
-  
-  /* 
-  Busmaster without s/g support? 
-  NOTE: old docs allowed busmasters to pass a NULL Adapter. In this case, MapRegisterBase 
-  not being NULL is used to detect a non s/g busmaster.
-  */
-  if ((!AdapterObject && MapRegisterBase) ||
-      (AdapterObject && AdapterObject->MasterDevice && !AdapterObject->ScatterGather))
-  {
-    /*
-    NOTE: Busmasters doing common-buffer DMA shouldn't call IoMapTransfer, but I don't
-    know if it's illegal... Maybe figure out what to do in this case...
-    */
-
-    if( WriteToDevice )
-    {
-      memcpy(MapRegisterBase,
-             (char*)MmGetSystemAddressForMdl(Mdl) + ((ULONG)CurrentVa - (ULONG)MmGetMdlVirtualAddress(Mdl)),
-             *Length );
-    }
-
-    return MmGetPhysicalAddress(MapRegisterBase);
-  }
-
-  DPRINT("IoMapTransfer: Unsupported operation\n");
-  KEBUGCHECK(0);
-  return Address;
-}
-
-
-/* EOF */
-
-
-
-
index 2011eb1..12eec16 100644 (file)
  * FILE:            ntoskrnl/hal/x86/dma.c
  * PURPOSE:         DMA functions
  * PROGRAMMERS:     David Welch (welch@mcmail.com)
+ *                  Filip Navara (navaraf@reactos.com)
  * UPDATE HISTORY:
  *                  Created 22/05/98
  */
 
+/**
+ * @page DMA Implementation Notes
+ *
+ * Concepts:
+ *
+ * - Map register
+ *
+ *   Abstract encapsulation of physically contiguous buffer that resides
+ *   in memory accessible by both the DMA device / controller and the system.
+ *   The map registers are allocated and distributed on demand and are
+ *   scarce resource.
+ *
+ *   The actual use of map registers is to allow transfers from/to buffer
+ *   located in physical memory at address inaccessible by the DMA device /
+ *   controller directly. For such transfers the map register buffers
+ *   are used as intermediate data storage.
+ *
+ * - Master adapter
+ *
+ *   A container for map registers (typically corresponding to one physical
+ *   bus connection type). There can be master adapters for 24-bit address
+ *   ranges, 32-bit address ranges, etc. Every time a new DMA adapter is
+ *   created it's associated with a corresponding master adapter that
+ *   is used for any map register allocation requests.
+ *
+ * - Bus-master / Slave DMA
+ *
+ *   Slave DMA is term used for DMA transfers done by the system (E)ISA
+ *   controller as opposed to transfers mastered by the device itself
+ *   (hence the name).
+ *
+ *   For slave DMA special care is taken to actually access the system
+ *   controller and handle the transfers. The relevant code is in
+ *   HalpDmaInitializeEisaAdapter, HalReadDmaCounter, IoFlushAdapterBuffers
+ *   and IoMapTransfer.
+ *
+ * Implementation:
+ *
+ * - Allocation of map registers
+ *
+ *   Initial set of map registers is allocated on the system start to
+ *   ensure that low memory won't get filled up later. Additional map
+ *   registers are allocated as needed by HalpGrowMapBuffers. This
+ *   routine is called on two places:
+ *
+ *   - HalGetAdapter, since we're at PASSIVE_LEVEL and it's known that
+ *     more map registers will probably be needed.
+ *   - IoAllocateAdapterChannel (indirectly using HalpGrowMapBufferWorker
+ *     since we're at DISPATCH_LEVEL and call HalpGrowMapBuffers directly)
+ *     when no more map registers are free.
+ *
+ *   Note that even if no more map registers can be allocated it's not
+ *   the end of the world. The adapters waiting for free map registers
+ *   are queued in the master adapter's queue and once one driver hands
+ *   back it's map registers (using IoFreeMapRegisters or indirectly using
+ *   the execution routine callback in IoAllocateAdapterChannel) the
+ *   queue gets processed and the map registers are reassigned.
+ */
+
 /* INCLUDES *****************************************************************/
 
 #include <hal.h>
 #define NDEBUG
 #include <debug.h>
 
-/* Adapters for each channel */
-PADAPTER_OBJECT HalpEisaAdapter[8];
+static KEVENT HalpDmaLock;
+static LIST_ENTRY HalpDmaAdapterList;
+static PADAPTER_OBJECT HalpEisaAdapter[8];
+static BOOLEAN HalpEisaDma;
+static PADAPTER_OBJECT HalpMasterAdapter;
+
+static const ULONG_PTR HalpEisaPortPage[8] = {
+   FIELD_OFFSET(DMA_PAGE, Channel0),
+   FIELD_OFFSET(DMA_PAGE, Channel1),
+   FIELD_OFFSET(DMA_PAGE, Channel2),
+   FIELD_OFFSET(DMA_PAGE, Channel3),
+   0,
+   FIELD_OFFSET(DMA_PAGE, Channel5),
+   FIELD_OFFSET(DMA_PAGE, Channel6),
+   FIELD_OFFSET(DMA_PAGE, Channel7)
+};
+
+static DMA_OPERATIONS HalpDmaOperations = {
+   sizeof(DMA_OPERATIONS),
+   (PPUT_DMA_ADAPTER)HalPutDmaAdapter,
+   (PALLOCATE_COMMON_BUFFER)HalAllocateCommonBuffer,
+   (PFREE_COMMON_BUFFER)HalFreeCommonBuffer,
+   (PALLOCATE_ADAPTER_CHANNEL)IoAllocateAdapterChannel,
+   (PFLUSH_ADAPTER_BUFFERS)IoFlushAdapterBuffers,
+   (PFREE_ADAPTER_CHANNEL)IoFreeAdapterChannel,
+   (PFREE_MAP_REGISTERS)IoFreeMapRegisters,
+   (PMAP_TRANSFER)IoMapTransfer,
+   (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*/,
+   NULL /*(PCALCULATE_SCATTER_GATHER_LIST_SIZE)HalCalculateScatterGatherListSize*/,
+   NULL /*(PBUILD_SCATTER_GATHER_LIST)HalBuildScatterGatherList*/,
+   NULL /*(PBUILD_MDL_FROM_SCATTER_GATHER_LIST)HalBuildMdlFromScatterGatherList*/
+};
+
+#define MAX_MAP_REGISTERS 64
+
+#define TAG_DMA TAG('D','M','A',' ')
 
 /* FUNCTIONS *****************************************************************/
 
 VOID
-HalpInitDma (VOID)
+HalpInitDma(VOID)
 {
-  /* TODO: Initialize the first Map Buffer */
+   /*
+    * Check if Extended DMA is available. We're just going to do a random
+    * read and write.
+    */
+    
+   WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2), 0x2A);
+   if (READ_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)) == 0x2A)
+      HalpEisaDma = TRUE;
+
+   /*
+    * Intialize all the global variables and allocate master adapter with
+    * first map buffers.
+    */
+
+   InitializeListHead(&HalpDmaAdapterList);
+   KeInitializeEvent(&HalpDmaLock, NotificationEvent, TRUE);
+
+   HalpMasterAdapter = HalpDmaAllocateMasterAdapter();
 }
 
-PVOID STDCALL
-HalAllocateCommonBuffer (PADAPTER_OBJECT    AdapterObject,
-                        ULONG              Length,
-                        PPHYSICAL_ADDRESS  LogicalAddress,
-                        BOOLEAN            CacheEnabled)
-/*
- * FUNCTION: Allocates memory that is visible to both the processor(s) and
- * a dma device
- * ARGUMENTS: 
- *         AdapterObject = Adapter object representing the bus master or
- *                         system dma controller
- *         Length = Number of bytes to allocate
- *         LogicalAddress = Logical address the driver can use to access the
- *                          buffer 
- *         CacheEnabled = Specifies if the memory can be cached
- * RETURNS: The base virtual address of the memory allocated
- *          NULL on failure
- * NOTES:
- *      CacheEnabled is ignored - it's all cache-disabled (like in NT)
- *      UPDATE: It's not ignored now. If that's wrong just modify the
- *      CacheEnabled comparsion below. 
+/**
+ * @name HalpGetAdapterMaximumPhysicalAddress
+ *
+ * Get the maximum physical address acceptable by the device represented
+ * by the passed DMA adapter.
  */
+
+PHYSICAL_ADDRESS STDCALL
+HalpGetAdapterMaximumPhysicalAddress(
+   IN PADAPTER_OBJECT AdapterObject)
 {
-  PHYSICAL_ADDRESS LowestAddress, HighestAddress, BoundryAddressMultiple;
-  PVOID BaseAddress;
-
-  LowestAddress.QuadPart = 0;
-  BoundryAddressMultiple.QuadPart = 0;
-  if ((AdapterObject->Dma64BitAddresses) && (AdapterObject->MasterDevice)) {
-      HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFLL; /* 64Bit: >4GB address range */
-
-  } else if ((AdapterObject->Dma32BitAddresses) && (AdapterObject->MasterDevice)) {
-      HighestAddress.QuadPart = 0xFFFFFFFF; /* 32Bit: 4GB address range */
-  } else {
-      HighestAddress.QuadPart = 0x00FFFFFF; /* 24Bit: 16MB address range */
-      if (AdapterObject->Width16Bits)
+   PHYSICAL_ADDRESS HighestAddress;
+
+   if (AdapterObject->MasterDevice)
+   {
+      if (AdapterObject->Dma64BitAddresses)
       {
-         BoundryAddressMultiple.QuadPart = 0x20000;  /* 128k boundary */
+         HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
+         return HighestAddress;
       }
-      else
+      else if (AdapterObject->Dma32BitAddresses)
       {
-         BoundryAddressMultiple.QuadPart = 0x10000;  /* 64k boundary */
+         HighestAddress.QuadPart = 0xFFFFFFFF;
+         return HighestAddress;
       }
-  }
+   }
+
+   HighestAddress.QuadPart = 0xFFFFFF;
+   return HighestAddress;
+}
+
+/**
+ * @name HalpGrowMapBuffers
+ *
+ * Allocate initial, or additional, map buffers for DMA master adapter.
+ *
+ * @param MasterAdapter 
+ *        DMA master adapter to allocate buffers for.
+ * @param SizeOfMapBuffers
+ *        Size of the map buffers to allocate (not including the size
+ *        already allocated).
+ */
+
+BOOLEAN STDCALL
+HalpGrowMapBuffers(
+   IN PADAPTER_OBJECT AdapterObject,
+   IN ULONG SizeOfMapBuffers)
+{
+   PVOID VirtualAddress;
+   PHYSICAL_ADDRESS PhysicalAddress;
+   PHYSICAL_ADDRESS HighestAcceptableAddress;
+   PHYSICAL_ADDRESS LowestAcceptableAddress;
+   PHYSICAL_ADDRESS BoundryAddressMultiple;
+   KIRQL OldIrql;
+   ULONG MapRegisterCount;
+
+   /* FIXME: Check if enough map register slots are available. */
+
+   MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers);
+
+   /*
+    * Allocate memory for the new map registers. For 32-bit adapters we use
+    * two passes in order not to waste scare resource (low memory).
+    */
+
+   HighestAcceptableAddress =
+      HalpGetAdapterMaximumPhysicalAddress(AdapterObject);
+   LowestAcceptableAddress.HighPart = 0;
+   LowestAcceptableAddress.LowPart =
+      HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0;
+   BoundryAddressMultiple.QuadPart = 0;
+   
+   VirtualAddress = MmAllocateContiguousMemorySpecifyCache(
+      MapRegisterCount << PAGE_SHIFT, LowestAcceptableAddress,
+      HighestAcceptableAddress, BoundryAddressMultiple, MmNonCached);
+
+   if (VirtualAddress == NULL && LowestAcceptableAddress.LowPart != 0)
+   {
+      LowestAcceptableAddress.LowPart = 0;
+      VirtualAddress = MmAllocateContiguousMemorySpecifyCache(
+         MapRegisterCount << PAGE_SHIFT, LowestAcceptableAddress,
+         HighestAcceptableAddress, BoundryAddressMultiple, MmNonCached);
+   }
+
+   if (VirtualAddress == NULL)
+      return FALSE;
+
+   /*
+    * All the following must be done with the master adapter lock held
+    * to prevent corruption.
+    */
+
+   OldIrql = KfAcquireSpinLock(&AdapterObject->SpinLock);
+
+   /*
+    * Setup map register entries for the buffer allocated. Each entry has
+    * a virtual and physical address and corresponds to PAGE_SIZE large
+    * buffer.
+    */
+   
+   if (MapRegisterCount > 0)
+   {
+      PMAP_REGISTER_ENTRY CurrentEntry, PreviousEntry;
+
+      CurrentEntry = AdapterObject->MapRegisterBase +
+                     AdapterObject->NumberOfMapRegisters;
+      do
+      {
+         /*
+          * Leave one entry free for every non-contiguous memory region
+          * in the map register bitmap. This ensures that we can search
+          * using RtlFindClearBits for contiguous map register regions.
+          *
+          * Also for non-EISA DMA leave one free entry for every 64Kb
+          * break, because the DMA controller can handle only coniguous
+          * 64Kb regions.
+          */
+
+         if (CurrentEntry != AdapterObject->MapRegisterBase)
+         {
+            PreviousEntry = CurrentEntry - 1;
+            if (PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE ==
+                PhysicalAddress.LowPart)
+            {
+               if (!HalpEisaDma)
+               {
+                  if ((PreviousEntry->PhysicalAddress.LowPart ^
+                       PhysicalAddress.LowPart) & 0xFFFF0000)
+                  {
+                     CurrentEntry++;
+                     AdapterObject->NumberOfMapRegisters++;
+                  }
+               }
+            }
+            else
+            {
+               CurrentEntry++;
+               AdapterObject->NumberOfMapRegisters++;
+            }
+         }
+
+         RtlClearBit(AdapterObject->MapRegisters,
+                     CurrentEntry - AdapterObject->MapRegisterBase);
+         CurrentEntry->VirtualAddress = VirtualAddress;
+         CurrentEntry->PhysicalAddress = PhysicalAddress;
+
+         PhysicalAddress.LowPart += PAGE_SIZE;
+         VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE);
+
+         CurrentEntry++;
+         AdapterObject->NumberOfMapRegisters++;
+         MapRegisterCount--;
+      }
+      while (MapRegisterCount != 0);
+   }
+
+   KfReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
+
+   return TRUE;
+}
+
+/**
+ * @name HalpDmaAllocateMasterAdapter
+ *
+ * Helper routine to allocate and initialize master adapter object and it's
+ * associated map register buffers.
+ *
+ * @see HalpInitDma
+ */
+
+PADAPTER_OBJECT STDCALL
+HalpDmaAllocateMasterAdapter(VOID)
+{
+   PADAPTER_OBJECT MasterAdapter;
+   ULONG Size, SizeOfBitmap;
 
-  BaseAddress = MmAllocateContiguousMemorySpecifyCache(
-      Length,
-      LowestAddress,
-      HighestAddress,
-      BoundryAddressMultiple,
-      CacheEnabled ? MmCached : MmNonCached);
-  if (!BaseAddress)
-    return 0;
+   SizeOfBitmap = MAX_MAP_REGISTERS;
+   Size = sizeof(ADAPTER_OBJECT);
+   Size += sizeof(RTL_BITMAP);
+   Size += (SizeOfBitmap + 7) >> 3;
 
-  *LogicalAddress = MmGetPhysicalAddress(BaseAddress);
+   MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA);
+   if (MasterAdapter == NULL)
+      return NULL;
 
-  return BaseAddress;
+   RtlZeroMemory(MasterAdapter, Size);
+
+   KeInitializeSpinLock(&MasterAdapter->SpinLock);
+   InitializeListHead(&MasterAdapter->AdapterQueue);
+
+   MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1);
+   RtlInitializeBitMap(
+      MasterAdapter->MapRegisters,
+      (PULONG)(MasterAdapter->MapRegisters + 1),
+      SizeOfBitmap);
+   RtlSetAllBits(MasterAdapter->MapRegisters);
+   MasterAdapter->NumberOfMapRegisters = 0;
+   MasterAdapter->CommittedMapRegisters = 0;
+
+   MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(
+      NonPagedPool,
+      SizeOfBitmap * sizeof(MAP_REGISTER_ENTRY),
+      TAG_DMA);
+   if (MasterAdapter->MapRegisterBase == NULL)
+   {
+      ExFreePool(MasterAdapter);
+      return NULL;
+   }
+
+   RtlZeroMemory(MasterAdapter->MapRegisterBase,
+                 SizeOfBitmap * sizeof(MAP_REGISTER_ENTRY));
+   if (!HalpGrowMapBuffers(MasterAdapter, 0x10000))
+   {
+      ExFreePool(MasterAdapter);
+      return NULL;
+   }
+
+   return MasterAdapter;
 }
 
+/**
+ * @name HalpDmaAllocateChildAdapter
+ *
+ * Helper routine of HalGetAdapter. Allocate child adapter object and
+ * fill out some basic fields.
+ *
+ * @see HalGetAdapter
+ */
+
+PADAPTER_OBJECT STDCALL
+HalpDmaAllocateChildAdapter(
+   ULONG NumberOfMapRegisters,
+   PDEVICE_DESCRIPTION DeviceDescription)
+{
+   PADAPTER_OBJECT AdapterObject;
+   OBJECT_ATTRIBUTES ObjectAttributes;
+   NTSTATUS Status;
+   HANDLE Handle;
+
+   InitializeObjectAttributes(
+      &ObjectAttributes,
+      NULL,
+      OBJ_KERNEL_HANDLE | OBJ_PERMANENT,
+      NULL,
+      NULL);
+
+   Status = ObCreateObject(
+      KernelMode,
+      IoAdapterObjectType,
+      &ObjectAttributes,
+      KernelMode,
+      NULL,
+      sizeof(ADAPTER_OBJECT),
+      0,
+      0,
+      (PVOID)&AdapterObject);
+   if (!NT_SUCCESS(Status))
+      return NULL;
+
+   Status = ObReferenceObjectByPointer(
+      AdapterObject,
+      FILE_READ_DATA | FILE_WRITE_DATA,
+      IoAdapterObjectType,
+      KernelMode);
+   if (!NT_SUCCESS(Status))
+      return NULL;
+   RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
+
+   Status = ObInsertObject(
+      AdapterObject,
+      NULL,
+      FILE_READ_DATA | FILE_WRITE_DATA,
+      0,
+      NULL,
+      &Handle);
+   if (!NT_SUCCESS(Status))
+      return NULL;
+
+   ZwClose(Handle);
+
+   AdapterObject->DmaHeader.Version = DeviceDescription->Version;
+   AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT);
+   AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations;
+   AdapterObject->MapRegistersPerChannel = 1;
+   AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
+   AdapterObject->ChannelNumber = 0xFF;
+   AdapterObject->MasterAdapter = HalpMasterAdapter;
+   KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
+
+   return AdapterObject;
+}
+
+/**
+ * @name HalpDmaInitializeEisaAdapter
+ *
+ * Setup DMA modes and extended modes for (E)ISA DMA adapter object.
+ */
+
 BOOLEAN STDCALL
-HalFlushCommonBuffer (ULONG    Unknown1,
-                     ULONG     Unknown2,
-                     ULONG     Unknown3,
-                     ULONG     Unknown4,
-                     ULONG     Unknown5,
-                     ULONG     Unknown6,
-                     ULONG     Unknown7,
-                     ULONG     Unknown8)
+HalpDmaInitializeEisaAdapter(
+   PADAPTER_OBJECT AdapterObject,
+   PDEVICE_DESCRIPTION DeviceDescription)
 {
+   UCHAR Controller;
+   DMA_MODE DmaMode = { Byte: 0 };
+   DMA_EXTENDED_MODE ExtendedMode = { Byte: 0 };
+   PVOID AdapterBaseVa;
+
+   Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1;
+
+   if (Controller == 1)
+      AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController1);
+   else
+      AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController2);
+
+   AdapterObject->AdapterNumber = Controller;
+   AdapterObject->ChannelNumber = DeviceDescription->DmaChannel & 3;
+   AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel];
+   AdapterObject->Width16Bits = FALSE;
+   AdapterObject->AdapterBaseVa = AdapterBaseVa;
+
+   if (HalpEisaDma)
+   {
+      ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber;
+
+      switch (DeviceDescription->DmaSpeed)
+      {
+         case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break;
+         case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break;
+         case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break;
+         case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break;
+         default:
+            return FALSE;
+      }
+
+      switch (DeviceDescription->DmaWidth)
+      {
+         case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break;
+         case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break;
+         case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break;
+         default:
+            return FALSE;
+      }
+
+      if (Controller == 1)
+         WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode1),
+                          ExtendedMode.Byte);
+      else
+         WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode2),
+                          ExtendedMode.Byte);
+   }
+   else
+   {
+      /*
+       * Validate setup for non-busmaster DMA adapter. Secondary controller 
+       * supports only 16-bit transfers and main controller supports only
+       * 8-bit transfers. Anything else is invalid.
+       */
+
+      if (!DeviceDescription->Master)
+      {
+         if (Controller == 2 && DeviceDescription->DmaWidth == Width16Bits)
+            AdapterObject->Width16Bits = TRUE;
+         else if (Controller != 1 || DeviceDescription->DmaWidth != Width8Bits)
+            return FALSE;
+      }
+   }
+
+   DmaMode.Channel = AdapterObject->ChannelNumber;
+   DmaMode.AutoInitialize = DeviceDescription->AutoInitialize;
+
+   /*
+    * Set the DMA request mode.
+    *
+    * For (E)ISA bus master devices just unmask (enable) the DMA channel
+    * and set it to cascade mode. Otherwise just select the right one
+    * bases on the passed device description.
+    */
+
+   if (DeviceDescription->Master)
+   {
+      DmaMode.RequestMode = CASCADE_REQUEST_MODE;
+      if (Controller == 1)
+      {
+         /* Set the Request Data */
+         WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode,
+                          DmaMode.Byte);
+         /* Unmask DMA Channel */
+         WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask,
+                          AdapterObject->ChannelNumber | DMA_CLEARMASK);
+      } else {
+         /* 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);
+      }
+   }
+   else
+   {
+      if (DeviceDescription->DemandMode)
+         DmaMode.RequestMode = DEMAND_REQUEST_MODE;
+      else
+         DmaMode.RequestMode = SINGLE_REQUEST_MODE;
+   }
+
+   AdapterObject->AdapterMode = DmaMode;
+
    return TRUE;
 }
 
+/**
+ * @name HalGetAdapter
+ *
+ * Allocate an adapter object for DMA device.
+ *
+ * @param DeviceDescription
+ *        Structure describing the attributes of the device.
+ * @param NumberOfMapRegisters
+ *        On return filled with the maximum number of map registers the
+ *        device driver can allocate for DMA transfer operations.
+ *
+ * @return The DMA adapter on success, NULL otherwise.
+ *
+ * @implemented
+ */
+
+PADAPTER_OBJECT STDCALL
+HalGetAdapter(
+   PDEVICE_DESCRIPTION DeviceDescription,
+   PULONG NumberOfMapRegisters)
+{
+   PADAPTER_OBJECT AdapterObject = NULL;
+   PADAPTER_OBJECT MasterAdapter;
+   BOOLEAN EisaAdapter;
+   ULONG MapRegisters;
+   ULONG MaximumLength;
+
+   /* Validate parameters in device description */
+   if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION2)
+      return NULL;
+
+   /*
+    * See if we're going to use ISA/EISA DMA adapter. These adapters are
+    * special since they're reused.
+    *
+    * 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 == Isa &&
+          DeviceDescription->DmaChannel >= 8)
+         EisaAdapter = FALSE;
+      else
+         EisaAdapter = TRUE;
+   }
+   else
+   {
+      EisaAdapter = FALSE;
+   }
+       
+   /*
+    * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used
+    * for cascading the controllers and it's not available for software use.
+    */
+
+   if (EisaAdapter && DeviceDescription->DmaChannel == 4)
+      return NULL;
+
+   /*
+    * Calculate the number of map registers.
+    *
+    * - For EISA and PCI scatter/gather no map registers are needed.
+    * - For ISA slave scatter/gather one map register is needed.
+    * - For all other cases the number of map registers depends on
+    *   DeviceDescription->MaximumLength.
+    */
+
+   MaximumLength = DeviceDescription->MaximumLength & MAXLONG;
+   if (DeviceDescription->ScatterGather &&
+       (DeviceDescription->InterfaceType == Eisa ||
+        DeviceDescription->InterfaceType == PCIBus))
+   {
+      MapRegisters = 0;
+   }
+   else if (DeviceDescription->ScatterGather &&
+            !DeviceDescription->Master)
+   {
+      MapRegisters = 1;
+   }
+   else
+   {
+      /*
+       * In the equation below the additional map register added by
+       * the "+1" accounts for the case when a transfer does not start
+       * at a page-aligned address.
+       */
+      MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1;
+      if (MapRegisters > 16)
+         MapRegisters = 16;
+   }
+
+   /*
+    * Acquire the DMA lock that is used to protect adapter lists and
+    * EISA adapter array.
+    */
+
+   KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode,
+                         FALSE, NULL);
+
+   /*
+    * Now we must get ahold of the adapter object. For first eight ISA/EISA
+    * channels there are static adapter objects that are reused and updated
+    * on succesive HalGetAdapter calls. In other cases a new adapter object
+    * is always created and it's to the DMA adapter list (HalpDmaAdapterList).
+    */
+
+   if (EisaAdapter)
+   {
+      AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel];
+      if (AdapterObject != NULL)
+      {
+         if (AdapterObject->NeedsMapRegisters && 
+             MapRegisters > AdapterObject->MapRegistersPerChannel)
+            AdapterObject->MapRegistersPerChannel = MapRegisters;
+      }
+   }
+
+   if (AdapterObject == NULL)
+   {
+      AdapterObject = HalpDmaAllocateChildAdapter(
+         MapRegisters, DeviceDescription);
+      if (AdapterObject == NULL)
+      {
+         KeSetEvent(&HalpDmaLock, 0, 0);
+         return NULL;
+      }
+
+      if (EisaAdapter)
+      {
+         HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject;
+      }
+
+      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
+      {
+         AdapterObject->NeedsMapRegisters = FALSE;
+         if (DeviceDescription->Master)
+            AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1;
+         else
+            AdapterObject->MapRegistersPerChannel = 1;
+      }
+   }
+
+   if (!EisaAdapter)
+      InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList);
+
+   /*
+    * Release the DMA lock. HalpDmaAdapterList and HalpEisaAdapter will
+    * no longer be touched, so we don't need it.
+    */
+
+   KeSetEvent(&HalpDmaLock, 0, 0);
+
+   /*
+    * Setup the values in the adapter object that are common for all
+    * types of buses.
+    */
+
+   if (DeviceDescription->Version >= DEVICE_DESCRIPTION_VERSION1)
+      AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount;
+   else
+      AdapterObject->IgnoreCount = 0;
+
+   AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
+   AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses;
+   AdapterObject->ScatterGather = DeviceDescription->ScatterGather;
+   AdapterObject->MasterDevice = DeviceDescription->Master;
+   *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel;
+
+   /*
+    * For non-(E)ISA adapters we have already done all the work. On the
+    * other hand for (E)ISA adapters we must still setup the DMA modes
+    * and prepare the controller.
+    */
+
+   if (EisaAdapter)
+   {
+      if (!HalpDmaInitializeEisaAdapter(AdapterObject, DeviceDescription))
+      {
+         ObfDereferenceObject(AdapterObject);
+         return NULL;
+      }
+   }
+
+   return AdapterObject;
+}
+
+/**
+ * @name HalPutDmaAdapter
+ *
+ * Internal routine to free DMA adapter and resources for reuse. It's exported
+ * using the DMA_OPERATIONS interface by HalGetAdapter.
+ *
+ * @see HalGetAdapter
+ */
+
+VOID STDCALL
+HalPutDmaAdapter(
+   PADAPTER_OBJECT AdapterObject)
+{
+   if (AdapterObject->ChannelNumber == 0xFF)
+   {
+      KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode,
+                            FALSE, NULL);
+      RemoveEntryList(&AdapterObject->AdapterList);
+      KeSetEvent(&HalpDmaLock, 0, 0);
+   }
+
+   ObfDereferenceObject(AdapterObject);
+}
+
+/**
+ * @name HalAllocateCommonBuffer
+ *
+ * Allocates memory that is visible to both the processor(s) and the DMA
+ * device.
+ *
+ * @param AdapterObject
+ *        Adapter object representing the bus master or system dma controller.
+ * @param Length
+ *        Number of bytes to allocate.
+ * @param LogicalAddress
+ *        Logical address the driver can use to access the buffer.
+ * @param CacheEnabled
+ *        Specifies if the memory can be cached.
+ *
+ * @return The base virtual address of the memory allocated or NULL on failure.
+ *
+ * @remarks
+ *    On real NT x86 systems the CacheEnabled parameter is ignored, we honour
+ *    it. If it proves to cause problems change it.
+ *
+ * @see HalFreeCommonBuffer
+ *
+ * @implemented
+ */
+
+PVOID STDCALL
+HalAllocateCommonBuffer(
+   PADAPTER_OBJECT AdapterObject,
+   ULONG Length,
+   PPHYSICAL_ADDRESS LogicalAddress,
+   BOOLEAN CacheEnabled)
+{
+   PHYSICAL_ADDRESS LowestAcceptableAddress;
+   PHYSICAL_ADDRESS HighestAcceptableAddress;
+   PHYSICAL_ADDRESS BoundryAddressMultiple;
+   PVOID VirtualAddress;
+
+   LowestAcceptableAddress.QuadPart = 0;
+   HighestAcceptableAddress =
+      HalpGetAdapterMaximumPhysicalAddress(AdapterObject);
+   BoundryAddressMultiple.QuadPart = 0;
+
+   /*
+    * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For
+    * slave DMA devices the 64Kb boundary mustn't be crossed since the
+    * controller wouldn't be able to handle it.
+    */
+
+   if (AdapterObject->MasterDevice)
+      BoundryAddressMultiple.HighPart = 1;
+   else
+      BoundryAddressMultiple.LowPart = 0x10000;
+
+   VirtualAddress = MmAllocateContiguousMemorySpecifyCache(
+      Length, LowestAcceptableAddress, HighestAcceptableAddress,
+      BoundryAddressMultiple, CacheEnabled ? MmCached : MmNonCached);
+   if (VirtualAddress == NULL)
+      return NULL;
+
+   *LogicalAddress = MmGetPhysicalAddress(VirtualAddress);
+
+   return VirtualAddress;
+}
+
+/**
+ * @name HalFreeCommonBuffer
+ *
+ * Free common buffer allocated with HalAllocateCommonBuffer.
+ *
+ * @see HalAllocateCommonBuffer
+ *
+ * @implemented
+ */
+
 VOID STDCALL
-HalFreeCommonBuffer (PADAPTER_OBJECT           AdapterObject,
-                    ULONG                      Length,
-                    PHYSICAL_ADDRESS   LogicalAddress,
-                    PVOID                      VirtualAddress,
-                    BOOLEAN                    CacheEnabled)
+HalFreeCommonBuffer(
+   PADAPTER_OBJECT AdapterObject,
+   ULONG Length,
+   PHYSICAL_ADDRESS LogicalAddress,
+   PVOID VirtualAddress,
+   BOOLEAN CacheEnabled)
 {
    MmFreeContiguousMemory(VirtualAddress);
 }
 
-PADAPTER_OBJECT STDCALL
-HalGetAdapter (PDEVICE_DESCRIPTION     DeviceDescription,
-              PULONG                   NumberOfMapRegisters)
+/**
+ * @name HalpDmaGetDmaAlignment
+ *
+ * Internal routine to return the DMA alignment requirement. It's exported
+ * using the DMA_OPERATIONS interface by HalGetAdapter.
+ *
+ * @see HalGetAdapter
+ */
+
+ULONG STDCALL
+HalpDmaGetDmaAlignment(
+   PADAPTER_OBJECT AdapterObject)
+{
+   return 1;
+}
+
 /*
- * FUNCTION: Returns a pointer to an adapter object for the DMA device 
- * defined in the device description structure
- * ARGUMENTS:
- *        DeviceDescription = Structure describing the attributes of the device
- *        NumberOfMapRegisters (OUT) = Returns the maximum number of map
- *                                     registers the device driver can
- *                                     allocate for DMA transfer operations
- * RETURNS: The allocated adapter object on success
- *          NULL on failure
- * TODO:
- *        Testing
+ * @name HalReadDmaCounter
+ *
+ * Read DMA operation progress counter.
+ *
+ * @implemented
  */
+
+ULONG STDCALL
+HalReadDmaCounter(
+   PADAPTER_OBJECT AdapterObject)
 {
-       PADAPTER_OBJECT AdapterObject;
-       DWORD ChannelSelect;
-       DWORD Controller;
-       ULONG MaximumLength;
-       BOOLEAN ChannelSetup = TRUE;
-       DMA_MODE DmaMode = {0}; 
-
-       DPRINT("Entered Function\n");
+   KIRQL OldIrql;
+   ULONG Count, OldCount;
+
+   ASSERT(!AdapterObject->MasterDevice);
+
+   /*
+    * Acquire the master adapter lock since we're going to mess with the
+    * system DMA controller registers and we really don't want anyone
+    * to do the same at the same time.
+    */
+
+   KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
   
-       /* Validate parameters in device description, and return a pointer to
-       the adapter object for the requested dma channel */
-       if(DeviceDescription->Version != DEVICE_DESCRIPTION_VERSION) {
-               DPRINT("Invalid Adapter version!\n");
-               return NULL;
-       }
-
-       DPRINT("Checking Interface Type: %x \n", DeviceDescription->InterfaceType);
-       if (DeviceDescription->InterfaceType == PCIBus) {
-               if (DeviceDescription->Master == FALSE) {
-                       DPRINT("Invalid request!\n");
-                       return NULL;
-               }
-               ChannelSetup = FALSE;
-       }
-       
-       /* There are only 8 DMA channels on ISA, so any request above this
-       should not get any channel setup */
-       if (DeviceDescription->DmaChannel >= 8) {
-               ChannelSetup = FALSE;
-       }
-       
-       /* Channel 4 is Reserved for Chaining, so you cant use it */
-       if (DeviceDescription->DmaChannel == 4 && ChannelSetup) {
-               DPRINT("Invalid request!\n");
-               return NULL;
-       }
-       
-       /* Devices that support Scatter/Gather do not need Map Registers */
-       if (DeviceDescription->ScatterGather ||
-           DeviceDescription->InterfaceType == PCIBus) {
-               *NumberOfMapRegisters = 0;
-       }
-       
-       /* Check if Extended DMA is available (we're just going to do a random read/write
-       I picked Channel 2 because it's the first Channel in the Register */
-       WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController1Pages.Channel2), 0x2A);
-       if (READ_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController1Pages.Channel2)) == 0x2A) {
-               HalpEisaDma = TRUE;
-       }
-        
-       /* Find out how many Map Registers we need */
-       DPRINT("Setting up Adapter Settings!\n");
-       MaximumLength = DeviceDescription->MaximumLength & 0x7FFFFFFF;
-        *NumberOfMapRegisters = BYTES_TO_PAGES(MaximumLength) + 1;
-       
-       /* Set the Channel Selection */
-       ChannelSelect = DeviceDescription->DmaChannel & 0x03;
-       DmaMode.Channel = ChannelSelect;
-       
-       /* Get the Controller Setup */
-       Controller = (DeviceDescription->DmaChannel & 0x04) ? 2 : 1;
-       
-       /* Get the Adapter Object */
-       if (HalpEisaAdapter[DeviceDescription->DmaChannel] != NULL) {
-       
-               /* Already allocated, return it */
-               DPRINT("Getting an Adapter Object from the Cache\n");
-               AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel];
-               
-               /* Do we need more Map Registers this time? */
-               if ((AdapterObject->NeedsMapRegisters) && 
-                   (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)) {
-                       AdapterObject->MapRegistersPerChannel = *NumberOfMapRegisters;
-               }
-               
-               } else {
-       
-               /* We have to allocate a new object! How exciting! */
-               DPRINT("Allocating a new Adapter Object\n");
-               AdapterObject = HalpAllocateAdapterEx(*NumberOfMapRegisters,
-                                                     FALSE,
-                                                     DeviceDescription->Dma32BitAddresses);
-
-               if (AdapterObject == NULL) return NULL;
-               
-               HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject;
-               
-               if (!*NumberOfMapRegisters) {
-                       /* Easy case, no Map Registers needed */
-                       AdapterObject->NeedsMapRegisters = FALSE;
-               
-                       /* If you're the master, you get all you want */
-                       if (DeviceDescription->Master) {
-                               AdapterObject->MapRegistersPerChannel= *NumberOfMapRegisters;
-                       } else {
-                               AdapterObject->MapRegistersPerChannel = 1;
-                       }
-               } else {
-                       /* We Desire Registers */
-                       AdapterObject->NeedsMapRegisters = TRUE;
-               
-                       /* The registers you want */
-                       AdapterObject->MapRegistersPerChannel = *NumberOfMapRegisters;
-               
-                       /* Increase commitment */
-                       MasterAdapter->CommittedMapRegisters += *NumberOfMapRegisters;
-               }
-       }
-       
-       /* Set up DMA Structure */
-       if (Controller == 1) {
-               AdapterObject->AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController1);
-       } else {
-               AdapterObject->AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController2);
-       }
-               
-       /* Set up Some Adapter Data */
-       DPRINT("Setting up an Adapter Object\n");
-       AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount;
-       AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
-       AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses;
-       AdapterObject->ScatterGather = DeviceDescription->ScatterGather;
-        AdapterObject->MasterDevice = DeviceDescription->Master;
-       if (DeviceDescription->InterfaceType != PCIBus) AdapterObject->LegacyAdapter = TRUE;
-       
-       /* Everything below is not required if we don't need a channel */
-       if (!ChannelSetup) {
-               DPRINT("Retuning Adapter Object without Channel Setup\n");
-               return AdapterObject;
-       }
-       
-       AdapterObject->ChannelNumber = ChannelSelect;
-       
-       
-       /* Set up the Page Port */
-       if (Controller == 1) {
-               switch (ChannelSelect) {
-               
-               case 0:
-                       AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel0) +
-                                                          FIELD_OFFSET(EISA_CONTROL, DmaController1Pages));
-                       break;
-               case 1:
-                       AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel1) +
-                                                          FIELD_OFFSET(EISA_CONTROL, DmaController1Pages));
-                       break;
-               case 2:
-                       AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel2) +
-                                                          FIELD_OFFSET(EISA_CONTROL, DmaController1Pages));
-                       break;
-               case 3:
-                       AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel3) +
-                                                          FIELD_OFFSET(EISA_CONTROL, DmaController1Pages));
-                       break;
-               }
-       
-               /* Set Controller Number */
-               AdapterObject->AdapterNumber = 1; 
-       } else {
-               switch (ChannelSelect) {
-               
-               case 1:
-                       AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel5) +
-                                                          FIELD_OFFSET(EISA_CONTROL, DmaController1Pages));
-                       break;
-               case 2:
-                       AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel6) +
-                                                          FIELD_OFFSET(EISA_CONTROL, DmaController1Pages));
-                       break;
-               case 3:
-                       AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel7) +
-                                                          FIELD_OFFSET(EISA_CONTROL, DmaController1Pages));
-                       break;
-               }
-               
-               /* Set Controller Number */
-               AdapterObject->AdapterNumber = 2; 
-       }
-       
-       /* Set up the Extended Register */
-       if (HalpEisaDma) {
-               DMA_EXTENDED_MODE ExtendedMode;
-               
-               ExtendedMode.ChannelNumber = ChannelSelect;
-       
-               switch (DeviceDescription->DmaSpeed) {
-               
-               case Compatible:
-                       ExtendedMode.TimingMode = COMPATIBLE_TIMING;
-                       break;
-               
-               case TypeA:
-                       ExtendedMode.TimingMode = TYPE_A_TIMING;
-                       break;
-                       
-               case TypeB:
-                       ExtendedMode.TimingMode = TYPE_B_TIMING;
-                       break;
-                       
-               case TypeC:
-                       ExtendedMode.TimingMode = BURST_TIMING;
-                       break;
-               
-               default:
-                       return NULL;
-               }
-       
-               switch (DeviceDescription->DmaWidth) {
-               
-               case Width8Bits:
-                       ExtendedMode.TransferSize = B_8BITS;
-                       break;
-               
-               case Width16Bits:
-                       ExtendedMode.TransferSize = B_16BITS;
-                       break;
-                       
-               case Width32Bits:
-                       ExtendedMode.TransferSize = B_32BITS;
-                       break;
-                       
-               default:
-                       return NULL;
-                               }
-               
-               if (Controller == 1) {
-                       WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode1),
-                                       *((PUCHAR)&ExtendedMode));
-               } else {
-                       WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode2),
-                                       *((PUCHAR)&ExtendedMode));
-               }
-       }
-
-       /* Do 8/16-bit validation */
-       DPRINT("Validating an Adapter Object\n");
-       if (!DeviceDescription->Master) {
-               if ((DeviceDescription->DmaWidth == Width8Bits) && (Controller != 1)) {
-                       return NULL; /* 8-bit is only avalable on Controller 1 */
-               } else if (DeviceDescription->DmaWidth == Width16Bits) {
-                       if (Controller != 2) {
-                               return NULL; /* 16-bit is only avalable on Controller 2 */
-                       } else {
-                               AdapterObject->Width16Bits = TRUE;
-                       }
-               }
-       }
-
-       DPRINT("Final DMA Request Mode Setting of the Adapter Object\n");
-
-       /* Set the DMA Request Modes */
-       if (DeviceDescription->Master) {
-               /* This is a cascade request */
-               DmaMode.RequestMode = CASCADE_REQUEST_MODE;
-               
-               /* Send the request */
-               if (AdapterObject->AdapterNumber == 1) {
-                       /* Set the Request Data */
-                       WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterObject->AdapterBaseVa)->Mode,
-                                       AdapterObject->AdapterModeByte);
-                                         
-                       /* Unmask DMA Channel */
-                       WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterObject->AdapterBaseVa)->SingleMask,
-                                       AdapterObject->ChannelNumber | DMA_CLEARMASK);
-               } else {
-                       /* Set the Request Data */
-                       WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterObject->AdapterBaseVa)->Mode,
-                                       AdapterObject->AdapterModeByte);
-                                 
-                       /* Unmask DMA Channel */
-                       WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterObject->AdapterBaseVa)->SingleMask,
-                                       AdapterObject->ChannelNumber | DMA_CLEARMASK);
-               }
-       } else if (DeviceDescription->DemandMode) {
-               /* This is a Demand request */
-               DmaMode.RequestMode = DEMAND_REQUEST_MODE;
-       } else {
-               /* Normal Request */
-               DmaMode.RequestMode = SINGLE_REQUEST_MODE;
-       }
+   /* Send the request to the specific controller. */
+   if (AdapterObject->AdapterNumber == 1)
+   {
+      PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
+
+      Count = 0xffff00;
+      do
+      {
+         OldCount = Count;
+         /* Send Reset */
+         WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
+         /* Read Count */
+         Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
+                                 [AdapterObject->ChannelNumber].DmaBaseCount);
+         Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
+                                  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
+      }
+      while (0xffff00 & (OldCount ^ Count));
+   }
+   else
+   {
+      PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
+
+      Count = 0xffff00;
+      do
+      {
+         OldCount = Count;
+         /* Send Reset */
+         WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
+         /* Read Count */
+         Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
+                                 [AdapterObject->ChannelNumber].DmaBaseCount);
+         Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
+                                  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
+      }
+      while (0xffff00 & (OldCount ^ Count));
+   }
+
+   KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
        
-       /* Auto Initialize Enabled or Not*/
-       DmaMode.AutoInitialize = DeviceDescription->AutoInitialize;
-       AdapterObject->AdapterMode = DmaMode;
-       return AdapterObject;
+   Count++;
+   if (AdapterObject->Width16Bits)
+      Count *= 2;
+
+   return Count;
 }
 
-ULONG STDCALL
-HalReadDmaCounter (PADAPTER_OBJECT     AdapterObject)
+/**
+ * @name HalpGrowMapBufferWorker
+ *
+ * Helper routine of HalAllocateAdapterChannel for allocating map registers
+ * at PASSIVE_LEVEL in work item.
+ */
+
+VOID STDCALL
+HalpGrowMapBufferWorker(PVOID DeferredContext)
+{
+   PGROW_WORK_ITEM WorkItem = (PGROW_WORK_ITEM)DeferredContext;
+   KIRQL OldIrql;
+   BOOLEAN Succeeded;
+
+   /*
+    * Try to allocate new map registers for the adapter.
+    *
+    * NOTE: The NT implementation actually tries to allocate more map
+    * registers than needed as an optimization.
+    */
+
+   KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode,
+                         FALSE, NULL);
+   Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter, 
+                                  WorkItem->NumberOfMapRegisters);
+   KeSetEvent(&HalpDmaLock, 0, 0);
+
+   if (Succeeded)
+   {
+      /*
+       * Flush the adapter queue now that new map registers are ready. The
+       * easiest way to do that is to call IoFreeMapRegisters to not free
+       * any registers. Note that we use the magic (PVOID)2 map register
+       * base to bypass the parameter checking.
+       */
+
+      OldIrql = KfRaiseIrql(DISPATCH_LEVEL);
+      IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
+      KfLowerIrql(OldIrql);
+   }
+
+   ExFreePool(WorkItem);
+}
+
+/**
+ * @name HalAllocateAdapterChannel
+ *
+ * Setup map registers for an adapter object.
+ *
+ * @param AdapterObject
+ *        Pointer to an ADAPTER_OBJECT to set up.
+ * @param WaitContextBlock
+ *        Context block to be used with ExecutionRoutine.
+ * @param NumberOfMapRegisters
+ *        Number of map registers requested.
+ * @param ExecutionRoutine
+ *        Callback to call when map registers are allocated.
+ *
+ * @return
+ *    If not enough map registers can be allocated then
+ *    STATUS_INSUFFICIENT_RESOURCES is returned. If the function
+ *    succeeds or the callback is queued for later delivering then
+ *    STATUS_SUCCESS is returned.
+ *
+ * @see IoFreeAdapterChannel
+ *
+ * @implemented
+ */
+
+NTSTATUS STDCALL
+HalAllocateAdapterChannel(
+   PADAPTER_OBJECT AdapterObject,
+   PWAIT_CONTEXT_BLOCK WaitContextBlock,
+   ULONG NumberOfMapRegisters,
+   PDRIVER_CONTROL ExecutionRoutine)
+{
+   PADAPTER_OBJECT MasterAdapter;
+   PGROW_WORK_ITEM WorkItem;
+   ULONG Index = ~0;
+   ULONG Result;
+   KIRQL OldIrql;
+   
+   ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+   /* Set up the wait context block in case we can't run right away. */
+   WaitContextBlock->DeviceRoutine = ExecutionRoutine;
+   WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
+
+   /* Returns true if queued, else returns false and sets the queue to busy */
+   if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue, &WaitContextBlock->WaitQueueEntry))
+      return STATUS_SUCCESS;
+
+   MasterAdapter = AdapterObject->MasterAdapter;
+
+   AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+   AdapterObject->CurrentWcb = WaitContextBlock;
+
+   if (NumberOfMapRegisters && AdapterObject->NeedsMapRegisters)
+   {
+      if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
+      {
+         AdapterObject->NumberOfMapRegisters = 0;
+         IoFreeAdapterChannel(AdapterObject);
+         return STATUS_INSUFFICIENT_RESOURCES;
+      }
+
+      /*
+       * Get the map registers. This is partly complicated by the fact
+       * that new map registers can only be allocated at PASSIVE_LEVEL
+       * and we're currently at DISPATCH_LEVEL. The following code has
+       * two code paths:
+       *
+       * - If there is no adapter queued for map register allocation,
+       *   try to see if enough contiguous map registers are present.
+       *   In case they're we can just get them and proceed further.
+       *
+       * - If some adapter is already present in the queue we must
+       *   respect the order of adapters asking for map registers and
+       *   so the fast case described above can't take place.
+       *   This case is also entered if not enough coniguous map
+       *   registers are present.
+       *
+       *   A work queue item is allocated and queued, the adapter is
+       *   also queued into the master adapter queue. The worker
+       *   routine does the job of allocating the map registers at
+       *   PASSIVE_LEVEL and calling the ExecutionRoutine.
+       */
+
+      OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
+
+      if (IsListEmpty(&MasterAdapter->AdapterQueue))
+      {
+         Index = RtlFindClearBitsAndSet(
+            MasterAdapter->MapRegisters, NumberOfMapRegisters, 0);
+         if (Index != ~0)
+         {
+            AdapterObject->MapRegisterBase =
+               MasterAdapter->MapRegisterBase + Index;
+            if (!AdapterObject->ScatterGather)
+            {
+               AdapterObject->MapRegisterBase =
+                  (PMAP_REGISTER_ENTRY)(
+                     (ULONG_PTR)AdapterObject->MapRegisterBase |
+                     MAP_BASE_SW_SG);
+            }
+         }
+      }
+
+      if (Index == ~0)
+      {
+         WorkItem = ExAllocatePoolWithTag(
+            NonPagedPool, sizeof(GROW_WORK_ITEM), TAG_DMA);
+         if (WorkItem == NULL)
+         {
+            KfReleaseSpinLock(&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;
+
+         ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue);
+
+         KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+
+         return STATUS_SUCCESS;
+      }
+
+      KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+   }
+   else
+   {
+      AdapterObject->MapRegisterBase = NULL;
+      AdapterObject->NumberOfMapRegisters = 0;
+   }
+
+   AdapterObject->CurrentWcb = WaitContextBlock;
+
+   Result = ExecutionRoutine(
+      WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp, 
+      AdapterObject->MapRegisterBase, WaitContextBlock->DeviceContext);
+
+   /* 
+    * Possible return values:
+    *
+    * - KeepObject
+    *   Don't free any resources, the ADAPTER_OBJECT is still in use and
+    *   the caller will call IoFreeAdapterChannel later.
+    *
+    * - DeallocateObject
+    *   Deallocate the map registers and release the ADAPTER_OBJECT, so
+    *   someone else can use it.
+    *
+    * - DeallocateObjectKeepRegisters
+    *   Release the ADAPTER_OBJECT, but hang on to the map registers. The
+    *   client will later call IoFreeMapRegisters.
+    *
+    * NOTE:
+    * IoFreeAdapterChannel runs the queue, so it must be called unless
+    * the adapter object is not to be freed.
+    */
+
+   if (Result == DeallocateObject)
+   {
+      IoFreeAdapterChannel(AdapterObject);
+   }
+   else if (Result == DeallocateObjectKeepRegisters)
+   {
+      AdapterObject->NumberOfMapRegisters = 0;
+      IoFreeAdapterChannel(AdapterObject);
+   }
+
+   return STATUS_SUCCESS;
+}
+
+/**
+ * @name IoFreeAdapterChannel
+ *
+ * Free DMA resources allocated by IoAllocateAdapterChannel.
+ *
+ * @param AdapterObject
+ *        Adapter object with resources to free.
+ *
+ * @remarks
+ *    This function releases map registers registers assigned to the DMA
+ *    adapter. After releasing the adapter, it checks the adapter's queue
+ *    and runs each queued device object in series until the queue is
+ *    empty. This is the only way the device queue is emptied.
+ *
+ * @see IoAllocateAdapterChannel
+ *
+ * @implemented
+ */
+
+VOID STDCALL
+IoFreeAdapterChannel(
+   PADAPTER_OBJECT AdapterObject)
+{
+   PADAPTER_OBJECT MasterAdapter;
+   PKDEVICE_QUEUE_ENTRY DeviceQueueEntry;
+   PWAIT_CONTEXT_BLOCK WaitContextBlock;
+   ULONG Index = ~0;
+   ULONG Result;
+   KIRQL OldIrql;
+
+   MasterAdapter = AdapterObject->MasterAdapter;
+   
+   for (;;)
+   {
+      /*
+       * To keep map registers, call here with AdapterObject->
+       * NumberOfMapRegisters set to zero. This trick is used in
+       * HalAllocateAdapterChannel for example.
+       */
+      if (AdapterObject->NumberOfMapRegisters)
+      {
+         IoFreeMapRegisters(
+            AdapterObject,
+            AdapterObject->MapRegisterBase,
+            AdapterObject->NumberOfMapRegisters);
+      }
+
+      DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
+      if (DeviceQueueEntry == NULL)
+      {
+         break;
+      }
+
+      WaitContextBlock = CONTAINING_RECORD(
+         DeviceQueueEntry,
+         WAIT_CONTEXT_BLOCK,
+         WaitQueueEntry);
+
+      AdapterObject->CurrentWcb = WaitContextBlock;
+      AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters;
+
+      if (WaitContextBlock->NumberOfMapRegisters &&
+          AdapterObject->MasterAdapter)
+      {
+         OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
+
+         if (IsListEmpty(&MasterAdapter->AdapterQueue))
+         {
+            Index = RtlFindClearBitsAndSet(
+               MasterAdapter->MapRegisters,
+               WaitContextBlock->NumberOfMapRegisters, 0);
+            if (Index != ~0)
+            {
+               AdapterObject->MapRegisterBase =
+                  MasterAdapter->MapRegisterBase + Index;
+               if (!AdapterObject->ScatterGather)
+               {
+                  AdapterObject->MapRegisterBase =
+                     (PMAP_REGISTER_ENTRY)(
+                        (ULONG_PTR)AdapterObject->MapRegisterBase |
+                        MAP_BASE_SW_SG);
+               }
+            }
+         }
+
+         if (Index == ~0)
+         {
+            InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
+            KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+            break;
+         }
+
+         KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+      }
+      else
+      {
+         AdapterObject->MapRegisterBase = NULL;
+         AdapterObject->NumberOfMapRegisters = 0;
+      }
+
+      /* Call the adapter control routine. */
+      Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(
+          WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp,
+          AdapterObject->MapRegisterBase, WaitContextBlock->DeviceContext);
+
+      switch (Result)
+      {
+         case KeepObject:
+            /*
+             * We're done until the caller manually calls IoFreeAdapterChannel
+             * or IoFreeMapRegisters.
+             */
+            return;
+
+         case DeallocateObjectKeepRegisters:
+            /*
+             * Hide the map registers so they aren't deallocated next time
+             * around.
+             */
+            AdapterObject->NumberOfMapRegisters = 0;
+            break;
+
+         default:
+            break;
+      }
+   }
+}
+
+/**
+ * @name IoFreeMapRegisters
+ *
+ * Free map registers reserved by the system for a DMA.
+ *
+ * @param AdapterObject
+ *        DMA adapter to free map registers on.
+ * @param MapRegisterBase
+ *        Handle to map registers to free.
+ * @param NumberOfRegisters
+ *        Number of map registers to be freed.
+ *
+ * @implemented
+ */
+
+VOID STDCALL
+IoFreeMapRegisters(
+   IN PADAPTER_OBJECT AdapterObject,
+   IN PVOID MapRegisterBase,
+   IN ULONG NumberOfMapRegisters)
 {
-  KIRQL OldIrql;
-  ULONG Count;
+   PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
+   PLIST_ENTRY ListEntry;
+   KIRQL OldIrql;
+   ULONG Index;
+   ULONG Result;
+
+   ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+   if (MasterAdapter == NULL || MapRegisterBase == NULL)
+      return;
+
+   OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
+
+   if (NumberOfMapRegisters != 0)
+   {
+      PMAP_REGISTER_ENTRY RealMapRegisterBase;
+
+      RealMapRegisterBase =
+         (PMAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
+      RtlClearBits(MasterAdapter->MapRegisters,
+                   RealMapRegisterBase - MasterAdapter->MapRegisterBase,
+                   NumberOfMapRegisters);
+   }
+
+   /*
+    * Now that we freed few map registers it's time to look at the master
+    * adapter queue and see if there is someone waiting for map registers.
+    */
+
+   while (!IsListEmpty(&MasterAdapter->AdapterQueue))
+   {
+      ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue);
+      AdapterObject = CONTAINING_RECORD(
+         ListEntry, struct _ADAPTER_OBJECT, AdapterQueue);
+
+      Index = RtlFindClearBitsAndSet(
+         MasterAdapter->MapRegisters,
+         AdapterObject->NumberOfMapRegisters,
+         MasterAdapter->NumberOfMapRegisters);
+      if (Index == ~0)
+      {
+         InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
+         break;
+      }
 
-       KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
+      KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+
+      AdapterObject->MapRegisterBase =
+         MasterAdapter->MapRegisterBase + Index;
+
+      Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(
+         AdapterObject->CurrentWcb->DeviceObject,
+         AdapterObject->CurrentWcb->CurrentIrp,
+         AdapterObject->MapRegisterBase,
+         AdapterObject->CurrentWcb->DeviceContext);
+
+      switch (Result)
+      {
+         case DeallocateObjectKeepRegisters:
+            AdapterObject->NumberOfMapRegisters = 0;
+            /* fall through */
+
+         case DeallocateObject:
+            if (AdapterObject->NumberOfMapRegisters)
+            {
+               OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
+               RtlClearBits(MasterAdapter->MapRegisters,
+                            AdapterObject->MapRegisterBase -
+                            MasterAdapter->MapRegisterBase,
+                            AdapterObject->NumberOfMapRegisters);
+               KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+            }
+            IoFreeAdapterChannel(AdapterObject);
+            break;
+
+         default:
+            break;
+      }
+
+      OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
+   }
+
+   KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+}
+
+/**
+ * @name HalpCopyBufferMap
+ *
+ * Helper function for copying data from/to map register buffers.
+ *
+ * @see IoFlushAdapterBuffers, IoMapTransfer
+ */
+
+VOID STDCALL
+HalpCopyBufferMap(
+   PMDL Mdl,
+   PMAP_REGISTER_ENTRY MapRegisterBase,
+   PVOID CurrentVa,
+   ULONG Length,
+   BOOLEAN WriteToDevice)
+{
+   ULONG CurrentLength;
+   ULONG_PTR CurrentAddress;
+   ULONG PageOffset;
+   PVOID VirtualAddress;
+
+   VirtualAddress = MmGetSystemAddressForMdlSafe(Mdl, HighPagePriority);
+   if (VirtualAddress == NULL)
+   {
+      /*
+       * NOTE: On real NT a mechanism with reserved pages is implemented
+       * to handle this case in a slow, but graceful non-fatal way.
+       */
+      /* FIXME: The correct bug check code isn't defined. */
+      /* KEBUGCHECKEX(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0); */
+      KEBUGCHECK(0);
+   }
+
+   CurrentAddress = (ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa -
+                    Mdl->ByteOffset;
+
+   while (Length > 0)
+   {
+      PageOffset = CurrentAddress & (PAGE_SIZE - 1);
+      CurrentLength = PAGE_SIZE - PageOffset;
+      if (CurrentLength > Length)
+         CurrentLength = Length;
+
+      if (WriteToDevice)
+      {
+         RtlCopyMemory(
+            (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + PageOffset),
+            (PVOID)CurrentAddress,
+            CurrentLength);
+      }
+      else
+      {
+         RtlCopyMemory(
+            (PVOID)CurrentAddress,
+            (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + PageOffset),
+            CurrentLength);
+      }
+
+      Length -= CurrentLength;
+      CurrentAddress += CurrentLength;
+      MapRegisterBase++;
+   }
+}
+
+/**
+ * @name IoFlushAdapterBuffers
+ *
+ * Flush any data remaining in the DMA controller's memory into the host
+ * memory.
+ *
+ * @param AdapterObject
+ *        The adapter object to flush.
+ * @param Mdl
+ *        Original MDL to flush data into.
+ * @param MapRegisterBase
+ *        Map register base that was just used by IoMapTransfer, etc.
+ * @param CurrentVa
+ *        Offset into Mdl to be flushed into, same as was passed to
+ *        IoMapTransfer.
+ * @param Length
+ *        Length of the buffer to be flushed into.
+ * @param WriteToDevice
+ *        TRUE if it's a write, FALSE if it's a read.
+ *
+ * @return TRUE in all cases.
+ *
+ * @remarks
+ *    This copies data from the map register-backed buffer to the user's
+ *    target buffer. Data are not in the user buffer until this function
+ *    is called.
+ *    For slave DMA transfers the controller channel is masked effectively
+ *    stopping the current transfer.
+ *
+ * @unimplemented.
+ */
+
+BOOLEAN STDCALL
+IoFlushAdapterBuffers(
+   PADAPTER_OBJECT AdapterObject,
+   PMDL Mdl,
+   PVOID MapRegisterBase,
+   PVOID CurrentVa,
+   ULONG Length,
+   BOOLEAN WriteToDevice)
+{
+   BOOLEAN SlaveDma = FALSE;
+   PMAP_REGISTER_ENTRY RealMapRegisterBase;
+
+   ASSERT_IRQL(DISPATCH_LEVEL);  
+
+   if (AdapterObject != NULL && !AdapterObject->MasterDevice)
+   {
+      /* Mask out (disable) the DMA channel. */
+      if (AdapterObject->AdapterNumber == 1)
+      {
+         PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
+         WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
+                          AdapterObject->ChannelNumber | DMA_SETMASK);
+      }
+      else
+      {
+         PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
+         WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
+                          AdapterObject->ChannelNumber | DMA_SETMASK);
+      }
+      SlaveDma = TRUE;
+   }
   
-       /* Send the Request to the specific controller */
-       if (AdapterObject->AdapterNumber == 1) {
-       
-               /* Set this for Ease */
-               PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
-       
-               /* Send Reset */
-               WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
-       
-               /* Read Count */
-               Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
-                                       [AdapterObject->ChannelNumber].DmaBaseCount);
-               Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
-                                       [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
+   /* This can happen if the device supports hardware scatter/gather. */
+   if (MapRegisterBase == NULL)
+      return TRUE;
+
+   RealMapRegisterBase =
+      (PMAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
+
+   if (!WriteToDevice)
+   {
+      if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG)
+      {
+         if (RealMapRegisterBase->Counter != ~0)
+         {
+            if (SlaveDma && !AdapterObject->IgnoreCount)
+               Length -= HalReadDmaCounter(AdapterObject);
+         }
+
+         HalpCopyBufferMap(Mdl, RealMapRegisterBase, CurrentVa, Length, 0);
+      }
+      else
+      {
+         /* FIXME: Unimplemented case */
+         ASSERT(FALSE);
+      }
+   }
+
+   RealMapRegisterBase->Counter = 0;
+
+   return TRUE;
+}
+
+/**
+ * @name IoMapTransfer
+ *
+ * Map a DMA for transfer and do the DMA if it's a slave.
+ *
+ * @param AdapterObject
+ *        Adapter object to do the DMA on. Bus-master may pass NULL.
+ * @param Mdl
+ *        Locked-down user buffer to DMA in to or out of.
+ * @param MapRegisterBase
+ *        Handle to map registers to use for this dma.
+ * @param CurrentVa
+ *        Index into Mdl to transfer into/out of.
+ * @param Length
+ *        Length of transfer. Number of bytes actually transferred on
+ *        output.
+ * @param WriteToDevice
+ *        TRUE if it's an output DMA, FALSE otherwise.
+ *
+ * @return
+ *    A logical address that can be used to program a DMA controller, it's
+ *    not meaningful for slave DMA device.
+ *
+ * @remarks
+ *    This function does a copyover to contiguous memory <16MB represented
+ *    by the map registers if needed. If the buffer described by MDL can be
+ *    used as is no copyover is done.
+ *    If it's a slave transfer, this function actually performs it.
+ *
+ * @implemented
+ */
+
+PHYSICAL_ADDRESS STDCALL
+IoMapTransfer(
+   IN PADAPTER_OBJECT AdapterObject,
+   IN PMDL Mdl,
+   IN PVOID MapRegisterBase,
+   IN PVOID CurrentVa,
+   IN OUT PULONG Length,
+   IN BOOLEAN WriteToDevice)
+{
+   PPFN_TYPE MdlPagesPtr;
+   PFN_TYPE MdlPage1, MdlPage2;
+   ULONG PageOffset;
+   ULONG TransferOffset;
+   ULONG TransferLength;
+   BOOLEAN UseMapRegisters;
+   PMAP_REGISTER_ENTRY RealMapRegisterBase;
+   PHYSICAL_ADDRESS PhysicalAddress;
+   PHYSICAL_ADDRESS HighestAcceptableAddress;
+   ULONG Counter;
+   DMA_MODE AdapterMode;
+   KIRQL OldIrql;
+   
+   /*
+    * Precalculate some values that are used in all cases.
+    *
+    * PageOffset is offset inside the page at which the transfer starts.
+    * MdlPagesPtr is pointer inside the MDL page chain at the page where the
+    *             transfer start.
+    * PhysicalAddress is physical address corresponding to the transfer
+    *                 start page and offset.
+    * TransferLength is the inital length of the transfer, which is reminder
+    *                of the first page. The actual value is calculated below.
+    *
+    * Note that all the variables can change during the processing which
+    * takes place below. These are just initial values.
+    */
+
+   PageOffset = (ULONG_PTR)CurrentVa & (PAGE_SIZE - 1);
+
+   MdlPagesPtr = (PPFN_TYPE)(Mdl + 1);
+   MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
+
+   PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
+   PhysicalAddress.QuadPart += PageOffset;
+
+   TransferLength = PAGE_SIZE - PageOffset;
+
+   /*
+    * Special case for bus master adapters with S/G support. We can directly
+    * use the buffer specified by the MDL, so not much work has to be done.
+    *
+    * Just return the passed VA's corresponding physical address and update
+    * length to the number of physically contiguous bytes found. Also
+    * pages crossing the 4Gb boundary aren't considered physically contiguous.
+    */
+
+   if (MapRegisterBase == NULL)
+   {
+      while (TransferLength < *Length)
+      {
+         MdlPage1 = *MdlPagesPtr;
+         MdlPage2 = *(MdlPagesPtr + 1);
+         if (MdlPage1 + 1 != MdlPage2)
+            break;
+         if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF)
+            break;
+         TransferLength += PAGE_SIZE;
+         MdlPagesPtr++;
+      }
+
+      if (TransferLength < *Length)
+         *Length = TransferLength;
+
+      return PhysicalAddress;
+   }
+
+   /*
+    * The code below applies to slave DMA adapters and bus master adapters
+    * without hardward S/G support.
+    */
+
+   RealMapRegisterBase =
+      (PMAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
+
+   /*
+    * Try to calculate the size of the transfer. We can only transfer
+    * pages that are physically contiguous and that don't cross the 
+    * 64Kb boundary (this limitation applies only for ISA controllers).
+    */
+
+   while (TransferLength < *Length)
+   {
+      MdlPage1 = *MdlPagesPtr;
+      MdlPage2 = *(MdlPagesPtr + 1);
+      if (MdlPage1 + 1 != MdlPage2)
+         break;
+      if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF))
+         break;
+      TransferLength += PAGE_SIZE;
+      MdlPagesPtr++;
+   }
+
+   if (TransferLength > *Length)
+      TransferLength = *Length;
+
+   /*
+    * If we're about to simulate software S/G and not all the pages are
+    * physically contiguous then we must use the map registers to store
+    * the data and allow the whole transfer to proceed at once.
+    */
+
+   if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG &&
+       TransferLength < *Length)
+   {
+      UseMapRegisters = TRUE;
+      PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
+      PhysicalAddress.QuadPart += PageOffset;
+      TransferLength = *Length;
+      RealMapRegisterBase->Counter = ~0;
+      Counter = 0;
+   }
+   else
+   {
+      /*
+       * This is ordinary DMA transfer, so just update the progress
+       * counters. These are used by IoFlushAdapterBuffers to track
+       * the transfer progress.
+       */
+
+      UseMapRegisters = FALSE;
+      Counter = RealMapRegisterBase->Counter;
+      RealMapRegisterBase->Counter +=
+         (PageOffset + TransferLength + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+
+      /*
+       * Check if the buffer doesn't exceed the highest phisical address
+       * limit of the device. In that case we must use the map registers to
+       * store the data.
+       */
+
+      HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject);
+      if (PhysicalAddress.QuadPart + TransferLength >
+          HighestAcceptableAddress.QuadPart)
+      {
+         UseMapRegisters = TRUE;
+         PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
+         PhysicalAddress.QuadPart += PageOffset;
+      }
+   }
+
+   /*
+    * If we decided to use the map registers (see above) and we're about
+    * to transfer data to the device then copy the buffers into the map
+    * register memory.
+    */
+
+   if (UseMapRegisters && WriteToDevice)
+   {
+      HalpCopyBufferMap(Mdl, RealMapRegisterBase + Counter,
+                        CurrentVa, TransferLength, WriteToDevice);
+   }
+
+   /*
+    * Return the length of transfer that actually takes place.
+    */
+
+   *Length = TransferLength;
+
+   /*
+    * If we're doing slave (system) DMA then program the (E)ISA controller
+    * to actually start the transfer.
+    */
+
+   if (AdapterObject != NULL && !AdapterObject->MasterDevice)
+   {
+      AdapterMode = AdapterObject->AdapterMode;
       
-       } else {
+      if (WriteToDevice)
+      {
+         AdapterMode.TransferType = WRITE_TRANSFER;
+      }
+      else
+      {
+         AdapterMode.TransferType = READ_TRANSFER;
+         if (AdapterObject->IgnoreCount)
+         {
+            RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress +
+                          PageOffset, TransferLength);
+         }
+      }
 
-               /* Set this for Ease */
-               PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
-       
-               /* Send Reset */
-               WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
-       
-               /* Read Count */
-               Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
-                                       [AdapterObject->ChannelNumber].DmaBaseCount);
-               Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
-                                       [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
-       }
-       
-       /* Play around with the count (add bias and multiply by 2 if 16-bit DMA) */
-       Count ++;
-       if (AdapterObject->Width16Bits) Count *=2 ;
-       
-       KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
-       
-       /* Return it */
-       return Count;
+      TransferOffset = PhysicalAddress.LowPart & 0xFFFF;
+      if (AdapterObject->Width16Bits)
+      {
+         TransferLength >>= 1;
+         TransferOffset >>= 1;
+      }
+
+      OldIrql = KfAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock);
+
+      if (AdapterObject->AdapterNumber == 1)
+      {
+         PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
+
+         /* 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));
+         if (HalpEisaDma)
+         {
+            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);
+      }
+      else
+      {
+         PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
+
+         /* 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));
+         if (HalpEisaDma)
+         {
+            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);
+      }
+
+      KfReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
+   }
+
+   /*
+    * Return physical address of the buffer with data that is used for the
+    * transfer. It can either point inside the Mdl that was passed by the
+    * caller or into the map registers if the Mdl buffer can't be used
+    * directly.
+    */
+
+   return PhysicalAddress;
+}
+
+/**
+ * @name HalFlushCommonBuffer
+ *
+ * @implemented
+ */
+
+BOOLEAN STDCALL
+HalFlushCommonBuffer(
+   ULONG Unknown1,
+   ULONG Unknown2,
+   ULONG Unknown3,
+   ULONG Unknown4,
+   ULONG Unknown5)
+{
+   return TRUE;
 }
 
 /* EOF */
index fdc06ae..2566f0e 100644 (file)
@@ -4,7 +4,6 @@
        <define name="_DISABLE_TIDENTS" />
        <define name="__USE_W32API" />
        <define name="_NTHAL_" />
-       <file>adapter.c</file>
        <file>beep.c</file>
        <file>bus.c</file>
        <file>dma.c</file>
index 745260b..e4befee 100644 (file)
@@ -26,6 +26,7 @@
 #include "apic.h"
 #include "bus.h"
 #include "halirq.h"
+#include "haldma.h"
 #include "halp.h"
 #include "mps.h"
 #include "ioapic.h"
diff --git a/reactos/hal/halx86/include/haldma.h b/reactos/hal/halx86/include/haldma.h
new file mode 100644 (file)
index 0000000..0c98a5a
--- /dev/null
@@ -0,0 +1,389 @@
+#ifndef HALDMA_H\r
+#define HALDMA_H\r
+\r
+/*\r
+ * DMA Page Register Structure  \r
+ * 080     DMA        RESERVED\r
+ * 081     DMA        Page Register (channel 2)\r
+ * 082     DMA        Page Register (channel 3)\r
+ * 083     DMA        Page Register (channel 1)\r
+ * 084     DMA        RESERVED\r
+ * 085     DMA        RESERVED\r
+ * 086     DMA        RESERVED\r
+ * 087     DMA        Page Register (channel 0)\r
+ * 088     DMA        RESERVED\r
+ * 089     PS/2-DMA   Page Register (channel 6)\r
+ * 08A     PS/2-DMA   Page Register (channel 7)\r
+ * 08B     PS/2-DMA   Page Register (channel 5)\r
+ * 08C     PS/2-DMA   RESERVED\r
+ * 08D     PS/2-DMA   RESERVED\r
+ * 08E     PS/2-DMA   RESERVED\r
+ * 08F     PS/2-DMA   Page Register (channel 4)\r
+ */\r
+\r
+typedef struct _DMA_PAGE\r
+{\r
+   UCHAR Reserved1;\r
+   UCHAR Channel2;\r
+   UCHAR Channel3;\r
+   UCHAR Channel1;\r
+   UCHAR Reserved2[3];\r
+   UCHAR Channel0;\r
+   UCHAR Reserved3;\r
+   UCHAR Channel6;\r
+   UCHAR Channel7;\r
+   UCHAR Channel5;\r
+   UCHAR Reserved4[3];\r
+   UCHAR Channel4;\r
+} DMA_PAGE, *PDMA_PAGE;\r
+\r
+/*\r
+ * DMA Channel Mask Register Structure\r
+ *\r
+ * MSB                             LSB\r
+ *       x   x   x   x     x   x   x   x\r
+ *       -------------------   -   -----\r
+ *                |            |     |     00 - Select channel 0 mask bit\r
+ *                |            |     \---- 01 - Select channel 1 mask bit\r
+ *                |            |           10 - Select channel 2 mask bit\r
+ *                |            |           11 - Select channel 3 mask bit\r
+ *                |            |\r
+ *                |            \----------  0 - Clear mask bit\r
+ *                |                         1 - Set mask bit\r
+ *                |\r
+ *                \----------------------- xx - Reserved\r
+ */\r
+\r
+typedef struct _DMA_CHANNEL_MASK\r
+{\r
+   UCHAR Channel: 2;\r
+   UCHAR SetMask: 1;\r
+   UCHAR Reserved: 5;\r
+} DMA_CHANNEL_MASK, *PDMA_CHANNEL_MASK;\r
+\r
+/*\r
+ * DMA Mask Register Structure \r
+ *\r
+ * MSB                             LSB\r
+ *    x   x   x   x     x   x   x   x\r
+ *    \---/   -   -     -----   -----\r
+ *      |     |   |       |       |     00 - Channel 0 select\r
+ *      |     |   |       |       \---- 01 - Channel 1 select\r
+ *      |     |   |       |             10 - Channel 2 select\r
+ *      |     |   |       |             11 - Channel 3 select\r
+ *      |     |   |       |\r
+ *      |     |   |       |             00 - Verify transfer\r
+ *      |     |   |       \------------ 01 - Write transfer\r
+ *      |     |   |                     10 - Read transfer\r
+ *      |     |   |\r
+ *      |     |   \--------------------  0 - Autoinitialized\r
+ *      |     |                          1 - Non-autoinitialized\r
+ *      |     |\r
+ *      |     \------------------------  0 - Address increment select\r
+ *      |\r
+ *      |                               00 - Demand mode\r
+ *      \------------------------------ 01 - Single mode\r
+ *                                      10 - Block mode\r
+ *                                      11 - Cascade mode\r
+ */\r
+\r
+typedef union _DMA_MODE\r
+{\r
+   struct\r
+   {\r
+      UCHAR Channel: 2;\r
+      UCHAR TransferType: 2;\r
+      UCHAR AutoInitialize: 1;\r
+      UCHAR AddressDecrement: 1;\r
+      UCHAR RequestMode: 2;\r
+   };\r
+   UCHAR Byte;\r
+} DMA_MODE, *PDMA_MODE;\r
+\r
+/*\r
+ * DMA Extended Mode Register Structure \r
+ *\r
+ * MSB                             LSB\r
+ *    x   x   x   x     x   x   x   x\r
+ *    -   -   -----     -----   -----\r
+ *    |   |     |         |       |     00 - Channel 0 select\r
+ *    |   |     |         |       \---- 01 - Channel 1 select\r
+ *    |   |     |         |             10 - Channel 2 select\r
+ *    |   |     |         |             11 - Channel 3 select\r
+ *    |   |     |         | \r
+ *    |   |     |         |             00 - 8-bit I/O, by bytes\r
+ *    |   |     |         \------------ 01 - 16-bit I/O, by words, address shifted\r
+ *    |   |     |                       10 - 32-bit I/O, by bytes\r
+ *    |   |     |                       11 - 16-bit I/O, by bytes\r
+ *    |   |     |\r
+ *    |   |     \---------------------- 00 - Compatible\r
+ *    |   |                             01 - Type A\r
+ *    |   |                             10 - Type B\r
+ *    |   |                             11 - Burst\r
+ *    |   |\r
+ *    |   \---------------------------- 0 - Terminal Count is Output\r
+ *    |                                 \r
+ *    \---------------------------------0 - Disable Stop Register\r
+ *                                      1 - Enable Stop Register\r
+ */\r
+\r
+typedef union _DMA_EXTENDED_MODE\r
+{\r
+   struct\r
+   {\r
+      UCHAR ChannelNumber: 2;\r
+      UCHAR TransferSize: 2;\r
+      UCHAR TimingMode: 2;\r
+      UCHAR TerminalCountIsOutput: 1;\r
+      UCHAR EnableStopRegister: 1;\r
+   };\r
+   UCHAR Byte;\r
+} DMA_EXTENDED_MODE, *PDMA_EXTENDED_MODE;\r
+\r
+/* DMA Extended Mode Register Transfer Sizes */\r
+#define B_8BITS 0\r
+#define W_16BITS 1\r
+#define B_32BITS 2\r
+#define B_16BITS 3\r
+\r
+/* DMA Extended Mode Register Timing */\r
+#define COMPATIBLE_TIMING 0\r
+#define TYPE_A_TIMING 1\r
+#define TYPE_B_TIMING 2\r
+#define BURST_TIMING 3\r
+\r
+/* Channel Stop Registers for each Channel */\r
+typedef struct _DMA_CHANNEL_STOP\r
+{\r
+   UCHAR ChannelLow;\r
+   UCHAR ChannelMid;\r
+   UCHAR ChannelHigh;\r
+   UCHAR Reserved;\r
+} DMA_CHANNEL_STOP, *PDMA_CHANNEL_STOP;\r
+\r
+/* Transfer Types */\r
+#define VERIFY_TRANSFER 0x00\r
+#define READ_TRANSFER 0x01\r
+#define WRITE_TRANSFER 0x02\r
+\r
+/* Request Modes */\r
+#define DEMAND_REQUEST_MODE 0x00\r
+#define SINGLE_REQUEST_MODE 0x01\r
+#define BLOCK_REQUEST_MODE 0x02\r
+#define CASCADE_REQUEST_MODE 0x03\r
+\r
+#define DMA_SETMASK 4\r
+#define DMA_CLEARMASK 0\r
+#define DMA_READ 4\r
+#define DMA_WRITE 8\r
+#define DMA_SINGLE_TRANSFER 0x40\r
+#define DMA_AUTO_INIT 0x10\r
+\r
+typedef struct _DMA1_ADDRESS_COUNT\r
+{\r
+   UCHAR DmaBaseAddress;\r
+   UCHAR DmaBaseCount; \r
+} DMA1_ADDRESS_COUNT, *PDMA1_ADDRESS_COUNT;\r
+\r
+typedef struct _DMA2_ADDRESS_COUNT\r
+{\r
+   UCHAR DmaBaseAddress;\r
+   UCHAR Reserved1;\r
+   UCHAR DmaBaseCount; \r
+   UCHAR Reserved2;\r
+} DMA2_ADDRESS_COUNT, *PDMA2_ADDRESS_COUNT;\r
+\r
+typedef struct _DMA1_CONTROL\r
+{\r
+   DMA1_ADDRESS_COUNT DmaAddressCount[4];\r
+   UCHAR DmaStatus;\r
+   UCHAR DmaRequest;\r
+   UCHAR SingleMask; \r
+   UCHAR Mode;\r
+   UCHAR ClearBytePointer;\r
+   UCHAR MasterClear;\r
+   UCHAR ClearMask;\r
+   UCHAR AllMask; \r
+} DMA1_CONTROL, *PDMA1_CONTROL;\r
+\r
+typedef struct _DMA2_CONTROL\r
+{\r
+   DMA2_ADDRESS_COUNT DmaAddressCount[4];\r
+   UCHAR DmaStatus;\r
+   UCHAR Reserved1;\r
+   UCHAR DmaRequest;\r
+   UCHAR Reserved2;\r
+   UCHAR SingleMask;\r
+   UCHAR Reserved3;\r
+   UCHAR Mode;\r
+   UCHAR Reserved4;\r
+   UCHAR ClearBytePointer;\r
+   UCHAR Reserved5;\r
+   UCHAR MasterClear;\r
+   UCHAR Reserved6;\r
+   UCHAR ClearMask;\r
+   UCHAR Reserved7;\r
+   UCHAR AllMask;\r
+   UCHAR Reserved8;\r
+} DMA2_CONTROL, *PDMA2_CONTROL;\r
+\r
+/* This structure defines the I/O Map of the 82537 controller. */\r
+typedef struct _EISA_CONTROL\r
+{\r
+   /* DMA Controller 1 */\r
+   DMA1_CONTROL DmaController1;         /* 00h-0Fh */\r
+   UCHAR Reserved1[16];                 /* 0Fh-1Fh */ \r
+   \r
+   /* Interrupt Controller 1 (PIC) */\r
+   UCHAR Pic1Operation;                 /* 20h     */\r
+   UCHAR Pic1Interrupt;                 /* 21h     */\r
+   UCHAR Reserved2[30];                 /* 22h-3Fh */\r
+   \r
+   /* Timer */\r
+   UCHAR TimerCounter;                  /* 40h     */\r
+   UCHAR TimerMemoryRefresh;            /* 41h     */\r
+   UCHAR Speaker;                       /* 42h     */\r
+   UCHAR TimerOperation;                /* 43h     */\r
+   UCHAR TimerMisc;                     /* 44h     */\r
+   UCHAR Reserved3[2];                  /* 45-46h  */\r
+   UCHAR TimerCounterControl;           /* 47h     */\r
+   UCHAR TimerFailSafeCounter;          /* 48h     */\r
+   UCHAR Reserved4;                     /* 49h     */\r
+   UCHAR TimerCounter2;                 /* 4Ah     */\r
+   UCHAR TimerOperation2;               /* 4Bh     */\r
+   UCHAR Reserved5[20];                 /* 4Ch-5Fh */\r
+   \r
+   /* NMI / Keyboard / RTC */\r
+   UCHAR Keyboard;                      /* 60h     */\r
+   UCHAR NmiStatus;                     /* 61h     */\r
+   UCHAR Reserved6[14];                 /* 62h-6Fh */\r
+   UCHAR NmiEnable;                     /* 70h     */\r
+   UCHAR Reserved7[15];                 /* 71h-7Fh */\r
+   \r
+   /* DMA Page Registers Controller 1 */\r
+   DMA_PAGE DmaController1Pages;        /* 80h-8Fh */\r
+   UCHAR Reserved8[16];                 /* 90h-9Fh */\r
+   \r
+    /* Interrupt Controller 2 (PIC) */\r
+   UCHAR Pic2Operation;                 /* 0A0h      */\r
+   UCHAR Pic2Interrupt;                 /* 0A1h      */\r
+   UCHAR Reserved9[30];                 /* 0A2h-0BFh */\r
+   \r
+   /* DMA Controller 2 */\r
+   DMA1_CONTROL DmaController2;         /* 0C0h-0CFh */\r
+   \r
+   /* System Reserved Ports */\r
+   UCHAR SystemReserved[816];           /* 0D0h-3FFh */\r
+   \r
+   /* Extended DMA Registers, Controller 1 */\r
+   UCHAR DmaHighByteCount1[8];          /* 400h-407h */\r
+   UCHAR Reserved10[2];                 /* 408h-409h */\r
+   UCHAR DmaChainMode1;                 /* 40Ah      */\r
+   UCHAR DmaExtendedMode1;              /* 40Bh      */\r
+   UCHAR DmaBufferControl;              /* 40Ch      */\r
+   UCHAR Reserved11[84];                /* 40Dh-460h */\r
+   UCHAR ExtendedNmiControl;            /* 461h      */\r
+   UCHAR NmiCommand;                    /* 462h      */\r
+   UCHAR Reserved12;                    /* 463h      */\r
+   UCHAR BusMaster;                     /* 464h      */\r
+   UCHAR Reserved13[27];                /* 465h-47Fh */\r
+   \r
+   /* DMA Page Registers Controller 2 */\r
+   DMA_PAGE DmaController2Pages;        /* 480h-48Fh */\r
+   UCHAR Reserved14[48];                /* 490h-4BFh */\r
+   \r
+   /* Extended DMA Registers, Controller 2 */\r
+   UCHAR DmaHighByteCount2[16];         /* 4C0h-4CFh */\r
+   \r
+   /* Edge/Level Control Registers */\r
+   UCHAR Pic1EdgeLevel;                 /* 4D0h      */\r
+   UCHAR Pic2EdgeLevel;                 /* 4D1h      */\r
+   UCHAR Reserved15[2];                 /* 4D2h-4D3h */\r
+  \r
+   /* Extended DMA Registers, Controller 2 */\r
+   UCHAR DmaChainMode2;                 /* 4D4h      */\r
+   UCHAR Reserved16;                    /* 4D5h      */\r
+   UCHAR DmaExtendedMode2;              /* 4D6h      */\r
+   UCHAR Reserved17[9];                 /* 4D7h-4DFh */\r
+   \r
+   /* DMA Stop Registers */\r
+   DMA_CHANNEL_STOP DmaChannelStop[8];  /* 4E0h-4FFh */\r
+} EISA_CONTROL, *PEISA_CONTROL;\r
+\r
+typedef struct _MAP_REGISTER_ENTRY\r
+{\r
+   PVOID VirtualAddress;\r
+   PHYSICAL_ADDRESS PhysicalAddress;\r
+   ULONG Counter;\r
+} MAP_REGISTER_ENTRY, *PMAP_REGISTER_ENTRY;\r
+\r
+struct _ADAPTER_OBJECT {\r
+   /*\r
+    * New style DMA object definition. The fact that it is at the beginning\r
+    * of the ADAPTER_OBJECT structure allows us to easily implement the\r
+    * fallback implementation of IoGetDmaAdapter.\r
+    */\r
+   DMA_ADAPTER DmaHeader;\r
+\r
+   /*\r
+    * For normal adapter objects pointer to master adapter that takes care\r
+    * of channel allocation. For master adapter set to NULL.\r
+    */ \r
+   struct _ADAPTER_OBJECT *MasterAdapter;\r
+\r
+   ULONG MapRegistersPerChannel;\r
+   PVOID AdapterBaseVa;\r
+   PMAP_REGISTER_ENTRY MapRegisterBase;\r
+\r
+   ULONG NumberOfMapRegisters;\r
+   ULONG CommittedMapRegisters;\r
+\r
+   PWAIT_CONTEXT_BLOCK CurrentWcb;\r
+   KDEVICE_QUEUE ChannelWaitQueue;\r
+   PKDEVICE_QUEUE RegisterWaitQueue;\r
+   LIST_ENTRY AdapterQueue;\r
+   KSPIN_LOCK SpinLock;\r
+   PRTL_BITMAP MapRegisters;\r
+   PUCHAR PagePort;\r
+   UCHAR ChannelNumber;\r
+   UCHAR AdapterNumber;\r
+   USHORT DmaPortAddress;\r
+   DMA_MODE AdapterMode;\r
+   BOOLEAN NeedsMapRegisters;\r
+   BOOLEAN MasterDevice;\r
+   BOOLEAN Width16Bits;\r
+   BOOLEAN ScatterGather;\r
+   BOOLEAN IgnoreCount;\r
+   BOOLEAN Dma32BitAddresses;\r
+   BOOLEAN Dma64BitAddresses;\r
+   LIST_ENTRY AdapterList;\r
+} ADAPTER_OBJECT;\r
\r
+typedef struct _GROW_WORK_ITEM {\r
+   WORK_QUEUE_ITEM WorkQueueItem;\r
+   PADAPTER_OBJECT AdapterObject;\r
+   ULONG NumberOfMapRegisters;\r
+} GROW_WORK_ITEM, *PGROW_WORK_ITEM;\r
+\r
+#define MAP_BASE_SW_SG 1\r
+\r
+PADAPTER_OBJECT STDCALL\r
+HalpDmaAllocateMasterAdapter(VOID);\r
+\r
+VOID STDCALL\r
+HalPutDmaAdapter(\r
+   PADAPTER_OBJECT AdapterObject);\r
+\r
+ULONG STDCALL\r
+HalpDmaGetDmaAlignment(\r
+   PADAPTER_OBJECT AdapterObject);\r
+\r
+NTSTATUS STDCALL\r
+IoAllocateAdapterChannel(\r
+   IN PADAPTER_OBJECT AdapterObject,\r
+   IN PDEVICE_OBJECT DeviceObject,\r
+   IN ULONG NumberOfMapRegisters,\r
+   IN PDRIVER_CONTROL ExecutionRoutine,\r
+   IN PVOID Context);\r
+\r
+#endif /* HALDMA_H */\r
index 2e5c168..dbee3f2 100644 (file)
@@ -40,358 +40,6 @@ PVOID HalpMapPhysMemory(ULONG PhysAddr, ULONG Size);
 /* Non-generic initialization */
 VOID HalpInitPhase0 (PLOADER_PARAMETER_BLOCK LoaderBlock);
 
-/* DMA Page Register Structure  
- 080     DMA        RESERVED
- 081     DMA        Page Register (channel 2)
- 082     DMA        Page Register (channel 3)
- 083     DMA        Page Register (channel 1)
- 084     DMA        RESERVED
- 085     DMA        RESERVED
- 086     DMA        RESERVED
- 087     DMA        Page Register (channel 0)
- 088     DMA        RESERVED
- 089     PS/2-DMA   Page Register (channel 6)
- 08A     PS/2-DMA   Page Register (channel 7)
- 08B     PS/2-DMA   Page Register (channel 5)
- 08C     PS/2-DMA   RESERVED
- 08D     PS/2-DMA   RESERVED
- 08E     PS/2-DMA   RESERVED
- 08F     PS/2-DMA   Page Register (channel 4)
-*/
- typedef struct _DMA_PAGE{
-  UCHAR Reserved1;
-  UCHAR Channel2;
-  UCHAR Channel3;
-  UCHAR Channel1;
-  UCHAR Reserved2[3];
-  UCHAR Channel0;
-  UCHAR Reserved3;
-  UCHAR Channel6;
-  UCHAR Channel7;
-  UCHAR Channel5;
-  UCHAR Reserved4[3];
-  UCHAR Channel4;
-} DMA_PAGE, *PDMA_PAGE;
-
-/* DMA Channel Mask Register Structure
-
-MSB                             LSB
-      x   x   x   x     x   x   x   x
-      -------------------   -   -----
-               |            |     |     00 - Select channel 0 mask bit
-               |            |     \---- 01 - Select channel 1 mask bit
-               |            |           10 - Select channel 2 mask bit
-               |            |           11 - Select channel 3 mask bit
-               |            |
-               |            \----------  0 - Clear mask bit
-               |                         1 - Set mask bit
-               |
-               \----------------------- xx - Reserved
-*/
-typedef struct _DMA_CHANNEL_MASK {
-  UCHAR Channel : 2;
-  UCHAR SetMask : 1;
-  UCHAR Reserved : 5;
-} DMA_CHANNEL_MASK, *PDMA_CHANNEL_MASK;
-
-/* DMA Mask Register Structure 
-
-   MSB                             LSB
-      x   x   x   x     x   x   x   x
-      \---/   -   -     -----   -----
-        |     |   |       |       |     00 - Channel 0 select
-        |     |   |       |       \---- 01 - Channel 1 select
-        |     |   |       |             10 - Channel 2 select
-        |     |   |       |             11 - Channel 3 select
-        |     |   |       |
-        |     |   |       |             00 - Verify transfer
-        |     |   |       \------------ 01 - Write transfer
-        |     |   |                     10 - Read transfer
-        |     |   |
-        |     |   \--------------------  0 - Autoinitialized
-        |     |                          1 - Non-autoinitialized
-        |     |
-        |     \------------------------  0 - Address increment select
-        |
-        |                               00 - Demand mode
-        \------------------------------ 01 - Single mode
-                                        10 - Block mode
-                                        11 - Cascade mode
-*/
-typedef struct _DMA_MODE {
-  UCHAR Channel : 2;
-  UCHAR TransferType : 2;
-  UCHAR AutoInitialize : 1;
-  UCHAR AddressDecrement : 1;
-  UCHAR RequestMode : 2;
-} DMA_MODE, *PDMA_MODE;
-
-
-/* DMA Extended Mode Register Structure 
-
-   MSB                             LSB
-      x   x   x   x     x   x   x   x
-      -   -   -----     -----   -----
-      |   |     |         |       |     00 - Channel 0 select
-      |   |     |         |       \---- 01 - Channel 1 select
-      |   |     |         |             10 - Channel 2 select
-      |   |     |         |             11 - Channel 3 select
-      |   |     |         | 
-      |   |     |         |             00 - 8-bit I/O, by bytes
-      |   |     |         \------------ 01 - 16-bit I/O, by words, address shifted
-      |   |     |                       10 - 32-bit I/O, by bytes
-      |   |     |                       11 - 16-bit I/O, by bytes
-      |   |     |
-      |   |     \---------------------- 00 - Compatible
-      |   |                             01 - Type A
-      |   |                             10 - Type B
-      |   |                             11 - Burst
-      |   |
-      |   \---------------------------- 0 - Terminal Count is Output
-      |                                 
-      \---------------------------------0 - Disable Stop Register
-                                        1 - Enable Stop Register
-*/
-typedef struct _DMA_EXTENDED_MODE {
-    UCHAR ChannelNumber : 2;
-    UCHAR TransferSize : 2;
-    UCHAR TimingMode : 2;
-    UCHAR TerminalCountIsOutput : 1;
-    UCHAR EnableStopRegister : 1;
-}DMA_EXTENDED_MODE, *PDMA_EXTENDED_MODE;
-
-/* DMA Extended Mode Register Transfer Sizes */
-#define B_8BITS 0
-#define W_16BITS 1
-#define B_32BITS 2
-#define B_16BITS 3
-
-/* DMA Extended Mode Register Timing */
-#define COMPATIBLE_TIMING 0
-#define TYPE_A_TIMING 1
-#define TYPE_B_TIMING 2
-#define BURST_TIMING 3
-
-/* Channel Stop Registers for each Channel */
-typedef struct _DMA_CHANNEL_STOP {
-  UCHAR ChannelLow;
-  UCHAR ChannelMid;
-  UCHAR ChannelHigh;
-  UCHAR Reserved;
-} DMA_CHANNEL_STOP, *PDMA_CHANNEL_STOP;
-
-/* Transfer Types */
-#define VERIFY_TRANSFER 0x00
-#define READ_TRANSFER 0x01
-#define WRITE_TRANSFER 0x02
-
-/* Request Modes */
-#define DEMAND_REQUEST_MODE 0x00
-#define SINGLE_REQUEST_MODE 0x01
-#define BLOCK_REQUEST_MODE 0x02
-#define CASCADE_REQUEST_MODE 0x03
-
-#define DMA_SETMASK 4
-#define DMA_CLEARMASK 0
-#define DMA_READ 4
-#define DMA_WRITE 8
-#define DMA_SINGLE_TRANSFER 0x40
-#define DMA_AUTO_INIT 0x10
-
-typedef struct _DMA1_ADDRESS_COUNT {
-   UCHAR DmaBaseAddress;
-   UCHAR DmaBaseCount; 
-} DMA1_ADDRESS_COUNT, *PDMA1_ADDRESS_COUNT;
-
-typedef struct _DMA2_ADDRESS_COUNT {
-   UCHAR DmaBaseAddress;
-   UCHAR Reserved1;
-   UCHAR DmaBaseCount; 
-   UCHAR Reserved2;
-} DMA2_ADDRESS_COUNT, *PDMA2_ADDRESS_COUNT;
-
-typedef struct _DMA1_CONTROL {
-   DMA1_ADDRESS_COUNT DmaAddressCount[4];
-   UCHAR DmaStatus;
-   UCHAR DmaRequest;
-   UCHAR SingleMask; 
-   UCHAR Mode;
-   UCHAR ClearBytePointer;
-   UCHAR MasterClear;
-   UCHAR ClearMask;
-   UCHAR AllMask; 
-} DMA1_CONTROL, *PDMA1_CONTROL;
-
-typedef struct _DMA2_CONTROL {
-   DMA2_ADDRESS_COUNT DmaAddressCount[4];
-   UCHAR DmaStatus;
-   UCHAR Reserved1;
-   UCHAR DmaRequest;
-   UCHAR Reserved2;
-   UCHAR SingleMask;
-   UCHAR Reserved3;
-   UCHAR Mode;
-   UCHAR Reserved4;
-   UCHAR ClearBytePointer;
-   UCHAR Reserved5;
-   UCHAR MasterClear;
-   UCHAR Reserved6;
-   UCHAR ClearMask;
-   UCHAR Reserved7;
-   UCHAR AllMask;
-   UCHAR Reserved8;
-} DMA2_CONTROL, *PDMA2_CONTROL;
-
-/* This Structure Defines the I/O Map of the 82537 Controller
-   I've only defined the registers which are likely to be useful to us */
-typedef struct _EISA_CONTROL {
-   /* DMA Controller 1 */
-   DMA1_CONTROL DmaController1;         /* 00h-0Fh */
-   UCHAR Reserved1[16];                 /* 0Fh-1Fh */ 
-   
-   /* Interrupt Controller 1 (PIC) */
-   UCHAR Pic1Operation;                 /* 20h     */
-   UCHAR Pic1Interrupt;                 /* 21h     */
-   UCHAR Reserved2[30];                 /* 22h-3Fh */
-   
-   /* Timer */
-   UCHAR TimerCounter;                  /* 40h     */
-   UCHAR TimerMemoryRefresh;            /* 41h     */
-   UCHAR Speaker;                       /* 42h     */
-   UCHAR TimerOperation;                /* 43h     */
-   UCHAR TimerMisc;                     /* 44h     */
-   UCHAR Reserved3[2];                  /* 45-46h  */
-   UCHAR TimerCounterControl;           /* 47h     */
-   UCHAR TimerFailSafeCounter;          /* 48h     */
-   UCHAR Reserved4;                     /* 49h     */
-   UCHAR TimerCounter2;                 /* 4Ah     */
-   UCHAR TimerOperation2;               /* 4Bh     */
-   UCHAR Reserved5[20];                 /* 4Ch-5Fh */
-   
-   /* NMI / Keyboard / RTC */
-   UCHAR Keyboard;                      /* 60h     */
-   UCHAR NmiStatus;                     /* 61h     */
-   UCHAR Reserved6[14];                 /* 62h-6Fh */
-   UCHAR NmiEnable;                     /* 70h     */
-   UCHAR Reserved7[15];                 /* 71h-7Fh */
-   
-   /* DMA Page Registers Controller 1 */
-   DMA_PAGE DmaController1Pages;        /* 80h-8Fh */
-   UCHAR Reserved8[16];                 /* 90h-9Fh */
-   
-    /* Interrupt Controller 2 (PIC) */
-   UCHAR Pic2Operation;                 /* 0A0h      */
-   UCHAR Pic2Interrupt;                 /* 0A1h      */
-   UCHAR Reserved9[30];                 /* 0A2h-0BFh */
-   
-   /* DMA Controller 2 */
-   DMA1_CONTROL DmaController2;         /* 0C0h-0CFh */
-   
-   /* System Reserved Ports */
-   UCHAR SystemReserved[816];           /* 0D0h-3FFh */
-   
-   /* Extended DMA Registers, Controller 1 */
-   UCHAR DmaHighByteCount1[8];          /* 400h-407h */
-   UCHAR Reserved10[2];                 /* 408h-409h */
-   UCHAR DmaChainMode1;                 /* 40Ah      */
-   UCHAR DmaExtendedMode1;              /* 40Bh      */
-   UCHAR DmaBufferControl;              /* 40Ch      */
-   UCHAR Reserved11[84];                /* 40Dh-460h */
-   UCHAR ExtendedNmiControl;            /* 461h      */
-   UCHAR NmiCommand;                    /* 462h      */
-   UCHAR Reserved12;                    /* 463h      */
-   UCHAR BusMaster;                     /* 464h      */
-   UCHAR Reserved13[27];                /* 465h-47Fh */
-   
-   /* DMA Page Registers Controller 2 */
-   DMA_PAGE DmaController2Pages;        /* 480h-48Fh */
-   UCHAR Reserved14[48];                /* 490h-4BFh */
-   
-   /* Extended DMA Registers, Controller 2 */
-   UCHAR DmaHighByteCount2[16];         /* 4C0h-4CFh */
-   
-   /* Edge/Level Control Registers */
-   UCHAR Pic1EdgeLevel;                 /* 4D0h      */
-   UCHAR Pic2EdgeLevel;                 /* 4D1h      */
-   UCHAR Reserved15[2];                 /* 4D2h-4D3h */
-  
-   /* Extended DMA Registers, Controller 2 */
-   UCHAR DmaChainMode2;                 /* 4D4h      */
-   UCHAR Reserved16;                    /* 4D5h      */
-   UCHAR DmaExtendedMode2;              /* 4D6h      */
-   UCHAR Reserved17[9];                 /* 4D7h-4DFh */
-   
-   /* DMA Stop Registers */
-   DMA_CHANNEL_STOP DmaChannelStop[8];  /* 4E0h-4FFh */
-} EISA_CONTROL, *PEISA_CONTROL;
-
-extern ULONG HalpEisaDma;
-extern PADAPTER_OBJECT MasterAdapter;
-
-ULONG HalpEisaDma;
-PADAPTER_OBJECT MasterAdapter;
-
-/*
- * ADAPTER_OBJECT - Track a busmaster DMA adapter and its associated resources
- *
- * NOTES:
- *     - I've updated this to the Windows Object Defintion. 
- */
-struct _ADAPTER_OBJECT {
-  DMA_ADAPTER DmaHeader;
-  struct _ADAPTER_OBJECT *MasterAdapter;
-  ULONG MapRegistersPerChannel;
-  PVOID AdapterBaseVa;
-  PVOID MapRegisterBase;
-  ULONG NumberOfMapRegisters;
-  ULONG CommittedMapRegisters; 
-  PWAIT_CONTEXT_BLOCK CurrentWcb;
-  KDEVICE_QUEUE ChannelWaitQueue;
-  PKDEVICE_QUEUE RegisterWaitQueue;
-  LIST_ENTRY AdapterQueue;
-  ULONG SpinLock;
-  PRTL_BITMAP MapRegisters;
-  PUCHAR PagePort;
-  UCHAR ChannelNumber;
-  UCHAR AdapterNumber;
-  USHORT DmaPortAddress;
-  union {
-    DMA_MODE AdapterMode;
-    UCHAR AdapterModeByte;
-  };
-  BOOLEAN NeedsMapRegisters;
-  BOOLEAN MasterDevice;
-  UCHAR Width16Bits;
-  UCHAR ScatterGather;
-  UCHAR IgnoreCount;
-  UCHAR Dma32BitAddresses;
-  UCHAR Dma64BitAddresses;
-  BOOLEAN LegacyAdapter;
-  LIST_ENTRY AdapterList;
-} ADAPTER_OBJECT;
-/*
-struct _ADAPTER_OBJECT {
-  INTERFACE_TYPE InterfaceType;
-  BOOLEAN Master;
-  int Channel;
-  PVOID PagePort;
-  PVOID CountPort;
-  PVOID OffsetPort;
-  KSPIN_LOCK SpinLock;
-  PVOID Buffer;
-  BOOLEAN Inuse;
-  ULONG AvailableMapRegisters;
-  PVOID MapRegisterBase;
-  ULONG AllocatedMapRegisters;
-  PWAIT_CONTEXT_BLOCK WaitContextBlock;
-  KDEVICE_QUEUE DeviceQueue;
-  BOOLEAN ScatterGather;
-  BOOLEAN DemandMode;
-  BOOLEAN AutoInitialize;
-};
-*/
-
 /* sysinfo.c */
 NTSTATUS STDCALL
 HalpQuerySystemInformation(IN HAL_QUERY_INFORMATION_CLASS InformationClass,
@@ -399,7 +47,6 @@ HalpQuerySystemInformation(IN HAL_QUERY_INFORMATION_CLASS InformationClass,
                           IN OUT PVOID Buffer,
                           OUT PULONG ReturnedLength);
 
-
 /* Non-standard functions */
 VOID STDCALL
 HalReleaseDisplayOwnership();