ReactOS  0.4.14-dev-991-g696cdc6
dma.c File Reference
#include <hal.h>
#include <debug.h>
Include dependency graph for dma.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MAX_MAP_REGISTERS   64
 
#define TAG_DMA   ' AMD'
 

Functions

VOID HalpInitDma (VOID)
 
HalpGetAdapterMaximumPhysicalAddress

Get the maximum physical address acceptable by the device represented by the passed DMA adapter.

PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress (IN PADAPTER_OBJECT AdapterObject)
 
HalpGrowMapBuffers

Allocate initial, or additional, map buffers for DMA master adapter.

Parameters
MasterAdapterDMA master adapter to allocate buffers for.
SizeOfMapBuffersSize of the map buffers to allocate (not including the size already allocated).
BOOLEAN NTAPI HalpGrowMapBuffers (IN PADAPTER_OBJECT AdapterObject, IN ULONG SizeOfMapBuffers)
 
HalpDmaAllocateMasterAdapter

Helper routine to allocate and initialize master adapter object and it's associated map register buffers.

See also
HalpInitDma
PADAPTER_OBJECT NTAPI HalpDmaAllocateMasterAdapter (VOID)
 
HalpDmaAllocateChildAdapter

Helper routine of HalGetAdapter. Allocate child adapter object and fill out some basic fields.

See also
HalGetAdapter
PADAPTER_OBJECT NTAPI HalpDmaAllocateChildAdapter (ULONG NumberOfMapRegisters, PDEVICE_DESCRIPTION DeviceDescription)
 
HalpDmaInitializeEisaAdapter

Setup DMA modes and extended modes for (E)ISA DMA adapter object.

BOOLEAN NTAPI HalpDmaInitializeEisaAdapter (PADAPTER_OBJECT AdapterObject, PDEVICE_DESCRIPTION DeviceDescription)
 
HalGetAdapter

Allocate an adapter object for DMA device.

Parameters
DeviceDescriptionStructure describing the attributes of the device.
NumberOfMapRegistersOn return filled with the maximum number of map registers the device driver can allocate for DMA transfer operations.
Returns
The DMA adapter on success, NULL otherwise.

@implemented

PADAPTER_OBJECT NTAPI HalGetAdapter (PDEVICE_DESCRIPTION DeviceDescription, PULONG NumberOfMapRegisters)
 
HalpGetDmaAdapter

Internal routine to allocate PnP DMA adapter object. It's exported through HalDispatchTable and used by IoGetDmaAdapter.

See also
HalGetAdapter
PDMA_ADAPTER NTAPI HalpGetDmaAdapter (IN PVOID Context, IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
 
HalPutDmaAdapter

Internal routine to free DMA adapter and resources for reuse. It's exported using the DMA_OPERATIONS interface by HalGetAdapter.

See also
HalGetAdapter
VOID NTAPI HalPutDmaAdapter (PADAPTER_OBJECT AdapterObject)
 
HalAllocateCommonBuffer

Allocates memory that is visible to both the processor(s) and the DMA device.

Parameters
AdapterObjectAdapter object representing the bus master or system dma controller.
LengthNumber of bytes to allocate.
LogicalAddressLogical address the driver can use to access the buffer.
CacheEnabledSpecifies if the memory can be cached.
Returns
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 also
HalFreeCommonBuffer

@implemented

PVOID NTAPI HalAllocateCommonBuffer (PADAPTER_OBJECT AdapterObject, ULONG Length, PPHYSICAL_ADDRESS LogicalAddress, BOOLEAN CacheEnabled)
 
HalFreeCommonBuffer

Free common buffer allocated with HalAllocateCommonBuffer.

See also
HalAllocateCommonBuffer

@implemented

VOID NTAPI HalFreeCommonBuffer (PADAPTER_OBJECT AdapterObject, ULONG Length, PHYSICAL_ADDRESS LogicalAddress, PVOID VirtualAddress, BOOLEAN CacheEnabled)
 
HalpDmaGetDmaAlignment

Internal routine to return the DMA alignment requirement. It's exported using the DMA_OPERATIONS interface by HalGetAdapter.

See also
HalGetAdapter
ULONG NTAPI HalpDmaGetDmaAlignment (PADAPTER_OBJECT AdapterObject)
 
ULONG NTAPI HalReadDmaCounter (PADAPTER_OBJECT AdapterObject)
 
HalpGrowMapBufferWorker

Helper routine of HalAllocateAdapterChannel for allocating map registers at PASSIVE_LEVEL in work item.

VOID NTAPI HalpGrowMapBufferWorker (PVOID DeferredContext)
 
HalAllocateAdapterChannel

Setup map registers for an adapter object.

Parameters
AdapterObjectPointer to an ADAPTER_OBJECT to set up.
WaitContextBlockContext block to be used with ExecutionRoutine.
NumberOfMapRegistersNumber of map registers requested.
ExecutionRoutineCallback to call when map registers are allocated.
Returns
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 also
IoFreeAdapterChannel

@implemented

NTSTATUS NTAPI HalAllocateAdapterChannel (PADAPTER_OBJECT AdapterObject, PWAIT_CONTEXT_BLOCK WaitContextBlock, ULONG NumberOfMapRegisters, PDRIVER_CONTROL ExecutionRoutine)
 
IoFreeAdapterChannel

Free DMA resources allocated by IoAllocateAdapterChannel.

Parameters
AdapterObjectAdapter 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 also
IoAllocateAdapterChannel

@implemented

VOID NTAPI IoFreeAdapterChannel (PADAPTER_OBJECT AdapterObject)
 
IoFreeMapRegisters

Free map registers reserved by the system for a DMA.

Parameters
AdapterObjectDMA adapter to free map registers on.
MapRegisterBaseHandle to map registers to free.
NumberOfRegistersNumber of map registers to be freed.

@implemented

VOID NTAPI IoFreeMapRegisters (IN PADAPTER_OBJECT AdapterObject, IN PVOID MapRegisterBase, IN ULONG NumberOfMapRegisters)
 
HalpCopyBufferMap

Helper function for copying data from/to map register buffers.

See also
IoFlushAdapterBuffers, IoMapTransfer
VOID NTAPI HalpCopyBufferMap (PMDL Mdl, PROS_MAP_REGISTER_ENTRY MapRegisterBase, PVOID CurrentVa, ULONG Length, BOOLEAN WriteToDevice)
 
IoFlushAdapterBuffers

Flush any data remaining in the DMA controller's memory into the host memory.

Parameters
AdapterObjectThe adapter object to flush.
MdlOriginal MDL to flush data into.
MapRegisterBaseMap register base that was just used by IoMapTransfer, etc.
CurrentVaOffset into Mdl to be flushed into, same as was passed to IoMapTransfer.
LengthLength of the buffer to be flushed into.
WriteToDeviceTRUE if it's a write, FALSE if it's a read.
Returns
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 NTAPI IoFlushAdapterBuffers (PADAPTER_OBJECT AdapterObject, PMDL Mdl, PVOID MapRegisterBase, PVOID CurrentVa, ULONG Length, BOOLEAN WriteToDevice)
 
IoMapTransfer

Map a DMA for transfer and do the DMA if it's a slave.

Parameters
AdapterObjectAdapter object to do the DMA on. Bus-master may pass NULL.
MdlLocked-down user buffer to DMA in to or out of.
MapRegisterBaseHandle to map registers to use for this dma.
CurrentVaIndex into Mdl to transfer into/out of.
LengthLength of transfer. Number of bytes actually transferred on output.
WriteToDeviceTRUE if it's an output DMA, FALSE otherwise.
Returns
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 NTAPI IoMapTransfer (IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN OUT PULONG Length, IN BOOLEAN WriteToDevice)
 
HalFlushCommonBuffer

@implemented

BOOLEAN NTAPI HalFlushCommonBuffer (IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress)
 
PVOID NTAPI HalAllocateCrashDumpRegisters (IN PADAPTER_OBJECT AdapterObject, IN OUT PULONG NumberOfMapRegisters)
 

Variables

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]
 
static DMA_OPERATIONS HalpDmaOperations
 

Macro Definition Documentation

◆ MAX_MAP_REGISTERS

#define MAX_MAP_REGISTERS   64

Definition at line 114 of file dma.c.

◆ NDEBUG

#define NDEBUG

Definition at line 74 of file dma.c.

◆ TAG_DMA

#define TAG_DMA   ' AMD'

Definition at line 116 of file dma.c.

Function Documentation

◆ HalAllocateAdapterChannel()

NTSTATUS NTAPI HalAllocateAdapterChannel ( PADAPTER_OBJECT  AdapterObject,
PWAIT_CONTEXT_BLOCK  WaitContextBlock,
ULONG  NumberOfMapRegisters,
PDRIVER_CONTROL  ExecutionRoutine 
)

Definition at line 1067 of file dma.c.

1072 {
1073  PADAPTER_OBJECT MasterAdapter;
1074  PGROW_WORK_ITEM WorkItem;
1075  ULONG Index = MAXULONG;
1076  ULONG Result;
1077  KIRQL OldIrql;
1078 
1080 
1081  /* Set up the wait context block in case we can't run right away. */
1082  WaitContextBlock->DeviceRoutine = ExecutionRoutine;
1083  WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
1084 
1085  /* Returns true if queued, else returns false and sets the queue to busy */
1086  if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue, &WaitContextBlock->WaitQueueEntry))
1087  return STATUS_SUCCESS;
1088 
1089  MasterAdapter = AdapterObject->MasterAdapter;
1090 
1091  AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
1092  AdapterObject->CurrentWcb = WaitContextBlock;
1093 
1094  if (NumberOfMapRegisters && AdapterObject->NeedsMapRegisters)
1095  {
1096  if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
1097  {
1098  AdapterObject->NumberOfMapRegisters = 0;
1099  IoFreeAdapterChannel(AdapterObject);
1101  }
1102 
1103  /*
1104  * Get the map registers. This is partly complicated by the fact
1105  * that new map registers can only be allocated at PASSIVE_LEVEL
1106  * and we're currently at DISPATCH_LEVEL. The following code has
1107  * two code paths:
1108  *
1109  * - If there is no adapter queued for map register allocation,
1110  * try to see if enough contiguous map registers are present.
1111  * In case they're we can just get them and proceed further.
1112  *
1113  * - If some adapter is already present in the queue we must
1114  * respect the order of adapters asking for map registers and
1115  * so the fast case described above can't take place.
1116  * This case is also entered if not enough coniguous map
1117  * registers are present.
1118  *
1119  * A work queue item is allocated and queued, the adapter is
1120  * also queued into the master adapter queue. The worker
1121  * routine does the job of allocating the map registers at
1122  * PASSIVE_LEVEL and calling the ExecutionRoutine.
1123  */
1124 
1125  OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
1126 
1127  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1128  {
1130  MasterAdapter->MapRegisters, NumberOfMapRegisters, 0);
1131  if (Index != MAXULONG)
1132  {
1133  AdapterObject->MapRegisterBase =
1134  MasterAdapter->MapRegisterBase + Index;
1135  if (!AdapterObject->ScatterGather)
1136  {
1137  AdapterObject->MapRegisterBase =
1139  (ULONG_PTR)AdapterObject->MapRegisterBase |
1140  MAP_BASE_SW_SG);
1141  }
1142  }
1143  }
1144 
1145  if (Index == MAXULONG)
1146  {
1147  WorkItem = ExAllocatePoolWithTag(
1148  NonPagedPool, sizeof(GROW_WORK_ITEM), TAG_DMA);
1149  if (WorkItem == NULL)
1150  {
1151  KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1152  AdapterObject->NumberOfMapRegisters = 0;
1153  IoFreeAdapterChannel(AdapterObject);
1155  }
1156 
1157  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1158 
1160  &WorkItem->WorkQueueItem, HalpGrowMapBufferWorker, WorkItem);
1161  WorkItem->AdapterObject = AdapterObject;
1163 
1165 
1166  KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1167 
1168  return STATUS_SUCCESS;
1169  }
1170 
1171  KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1172  }
1173  else
1174  {
1175  AdapterObject->MapRegisterBase = NULL;
1176  AdapterObject->NumberOfMapRegisters = 0;
1177  }
1178 
1179  AdapterObject->CurrentWcb = WaitContextBlock;
1180 
1182  WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp,
1183  AdapterObject->MapRegisterBase, WaitContextBlock->DeviceContext);
1184 
1185  /*
1186  * Possible return values:
1187  *
1188  * - KeepObject
1189  * Don't free any resources, the ADAPTER_OBJECT is still in use and
1190  * the caller will call IoFreeAdapterChannel later.
1191  *
1192  * - DeallocateObject
1193  * Deallocate the map registers and release the ADAPTER_OBJECT, so
1194  * someone else can use it.
1195  *
1196  * - DeallocateObjectKeepRegisters
1197  * Release the ADAPTER_OBJECT, but hang on to the map registers. The
1198  * client will later call IoFreeMapRegisters.
1199  *
1200  * NOTE:
1201  * IoFreeAdapterChannel runs the queue, so it must be called unless
1202  * the adapter object is not to be freed.
1203  */
1204 
1205  if (Result == DeallocateObject)
1206  {
1207  IoFreeAdapterChannel(AdapterObject);
1208  }
1210  {
1211  AdapterObject->NumberOfMapRegisters = 0;
1212  IoFreeAdapterChannel(AdapterObject);
1213  }
1214 
1215  return STATUS_SUCCESS;
1216 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:717
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
PDRIVER_CONTROL DeviceRoutine
Definition: iotypes.h:196
#define InsertTailList(ListHead, Entry)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
WORK_QUEUE_ITEM WorkQueueItem
Definition: haldma.h:362
uint32_t ULONG_PTR
Definition: typedefs.h:64
UCHAR KIRQL
Definition: env_spec_w32.h:591
PADAPTER_OBJECT AdapterObject
Definition: haldma.h:363
smooth NULL
Definition: ftsmooth.c:416
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
VOID NTAPI IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:103
VOID NTAPI HalpGrowMapBufferWorker(PVOID DeferredContext)
Definition: dma.c:1005
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
VOID FASTCALL KfReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL OldIrql)
Definition: spinlock.c:96
static const UCHAR Index[8]
Definition: usbohci.c:18
BOOLEAN NTAPI KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
Definition: devqueue.c:41
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TAG_DMA
Definition: dma.c:116
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
KDEVICE_QUEUE_ENTRY WaitQueueEntry
Definition: iotypes.h:195
#define MAXULONG
Definition: typedefs.h:251
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
_In_ PDEVICE_OBJECT _In_ ULONG _In_ PDRIVER_CONTROL ExecutionRoutine
Definition: iofuncs.h:1393
KIRQL FASTCALL KfAcquireSpinLock(PKSPIN_LOCK SpinLock)
Definition: spinlock.c:85
unsigned int ULONG
Definition: retypes.h:1
ULONG NumberOfMapRegisters
Definition: haldma.h:364
#define MAP_BASE_SW_SG
Definition: haldma.h:367
return STATUS_SUCCESS
Definition: btrfs.c:2938
ULONG NumberOfMapRegisters
Definition: iotypes.h:198

◆ HalAllocateCommonBuffer()

PVOID NTAPI HalAllocateCommonBuffer ( PADAPTER_OBJECT  AdapterObject,
ULONG  Length,
PPHYSICAL_ADDRESS  LogicalAddress,
BOOLEAN  CacheEnabled 
)

Definition at line 849 of file dma.c.

854 {
857  PHYSICAL_ADDRESS BoundryAddressMultiple;
859 
863  BoundryAddressMultiple.QuadPart = 0;
864 
865  /*
866  * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For
867  * slave DMA devices the 64Kb boundary mustn't be crossed since the
868  * controller wouldn't be able to handle it.
869  */
870 
871  if (AdapterObject->MasterDevice)
872  BoundryAddressMultiple.HighPart = 1;
873  else
874  BoundryAddressMultiple.LowPart = 0x10000;
875 
878  BoundryAddressMultiple, CacheEnabled ? MmCached : MmNonCached);
879  if (VirtualAddress == NULL)
880  return NULL;
881 
882  *LogicalAddress = MmGetPhysicalAddress(VirtualAddress);
883 
884  return VirtualAddress;
885 }
PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:167
smooth NULL
Definition: ftsmooth.c:416
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_Out_ PNDIS_HANDLE _Out_ PUINT _In_ PNDIS_STRING _In_ NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
Definition: ndis.h:3227
ULONG LowPart
Definition: typedefs.h:105
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3791
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS LowestAcceptableAddress
Definition: mmfuncs.h:214
PHYSICAL_ADDRESS NTAPI MmGetPhysicalAddress(IN PVOID Address)
Definition: stubs.c:682
LONGLONG QuadPart
Definition: typedefs.h:113
PVOID NTAPI MmAllocateContiguousMemorySpecifyCache(IN SIZE_T NumberOfBytes, IN PHYSICAL_ADDRESS LowestAcceptableAddress OPTIONAL, IN PHYSICAL_ADDRESS HighestAcceptableAddress, IN PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL, IN MEMORY_CACHING_TYPE CacheType OPTIONAL)
Definition: contmem.c:574

◆ HalAllocateCrashDumpRegisters()

PVOID NTAPI HalAllocateCrashDumpRegisters ( IN PADAPTER_OBJECT  AdapterObject,
IN OUT PULONG  NumberOfMapRegisters 
)

Definition at line 1964 of file dma.c.

1966 {
1967  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
1968  ULONG MapRegisterNumber;
1969 
1970  /* Check if it needs map registers */
1971  if (AdapterObject->NeedsMapRegisters)
1972  {
1973  /* Check if we have enough */
1974  if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
1975  {
1976  /* We don't, fail */
1977  AdapterObject->NumberOfMapRegisters = 0;
1978  return NULL;
1979  }
1980 
1981  /* Try to find free map registers */
1982  MapRegisterNumber = MAXULONG;
1983  MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1985  0);
1986 
1987  /* Check if nothing was found */
1988  if (MapRegisterNumber == MAXULONG)
1989  {
1990  /* No free registers found, so use the base registers */
1991  RtlSetBits(MasterAdapter->MapRegisters,
1992  0,
1994  MapRegisterNumber = 0;
1995  }
1996 
1997  /* Calculate the new base */
1998  AdapterObject->MapRegisterBase =
1999  (PROS_MAP_REGISTER_ENTRY)(MasterAdapter->MapRegisterBase +
2000  MapRegisterNumber);
2001 
2002  /* Check if scatter gather isn't supported */
2003  if (!AdapterObject->ScatterGather)
2004  {
2005  /* Set the flag */
2006  AdapterObject->MapRegisterBase =
2008  ((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
2009  }
2010  }
2011  else
2012  {
2013  AdapterObject->MapRegisterBase = NULL;
2014  AdapterObject->NumberOfMapRegisters = 0;
2015  }
2016 
2017  /* Return the base */
2018  return AdapterObject->MapRegisterBase;
2019 }
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
uint32_t ULONG_PTR
Definition: typedefs.h:64
smooth NULL
Definition: ftsmooth.c:416
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
#define MAXULONG
Definition: typedefs.h:251
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
unsigned int ULONG
Definition: retypes.h:1
#define MAP_BASE_SW_SG
Definition: haldma.h:367

◆ HalFlushCommonBuffer()

BOOLEAN NTAPI HalFlushCommonBuffer ( IN PADAPTER_OBJECT  AdapterObject,
IN ULONG  Length,
IN PHYSICAL_ADDRESS  LogicalAddress,
IN PVOID  VirtualAddress 
)

Definition at line 1950 of file dma.c.

1954 {
1955  /* Function always returns true */
1956  return TRUE;
1957 }
#define TRUE
Definition: types.h:120

◆ HalFreeCommonBuffer()

VOID NTAPI HalFreeCommonBuffer ( PADAPTER_OBJECT  AdapterObject,
ULONG  Length,
PHYSICAL_ADDRESS  LogicalAddress,
PVOID  VirtualAddress,
BOOLEAN  CacheEnabled 
)

Definition at line 898 of file dma.c.

904 {
906 }
VOID NTAPI MmFreeContiguousMemory(IN PVOID BaseAddress)
Definition: contmem.c:653
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3791

◆ HalGetAdapter()

PADAPTER_OBJECT NTAPI HalGetAdapter ( PDEVICE_DESCRIPTION  DeviceDescription,
PULONG  NumberOfMapRegisters 
)

Definition at line 591 of file dma.c.

594 {
595  PADAPTER_OBJECT AdapterObject = NULL;
596  PADAPTER_OBJECT MasterAdapter;
598  ULONG MapRegisters;
600 
601  /* Validate parameters in device description */
603  return NULL;
604 
605  /*
606  * See if we're going to use ISA/EISA DMA adapter. These adapters are
607  * special since they're reused.
608  *
609  * Also note that we check for channel number since there are only 8 DMA
610  * channels on ISA, so any request above this requires new adapter.
611  */
612 
614  {
617  EisaAdapter = FALSE;
618  else
619  EisaAdapter = TRUE;
620  }
621  else
622  {
623  EisaAdapter = FALSE;
624  }
625 
626  /*
627  * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used
628  * for cascading the controllers and it's not available for software use.
629  */
630 
632  return NULL;
633 
634  /*
635  * Calculate the number of map registers.
636  *
637  * - For EISA and PCI scatter/gather no map registers are needed.
638  * - For ISA slave scatter/gather one map register is needed.
639  * - For all other cases the number of map registers depends on
640  * DeviceDescription->MaximumLength.
641  */
642 
647  {
648  MapRegisters = 0;
649  }
650  else if (DeviceDescription->ScatterGather &&
652  {
653  MapRegisters = 1;
654  }
655  else
656  {
657  /*
658  * In the equation below the additional map register added by
659  * the "+1" accounts for the case when a transfer does not start
660  * at a page-aligned address.
661  */
662  MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1;
663  if (MapRegisters > 16)
664  MapRegisters = 16;
665  }
666 
667  /*
668  * Acquire the DMA lock that is used to protect adapter lists and
669  * EISA adapter array.
670  */
671 
673  FALSE, NULL);
674 
675  /*
676  * Now we must get ahold of the adapter object. For first eight ISA/EISA
677  * channels there are static adapter objects that are reused and updated
678  * on succesive HalGetAdapter calls. In other cases a new adapter object
679  * is always created and it's to the DMA adapter list (HalpDmaAdapterList).
680  */
681 
682  if (EisaAdapter)
683  {
684  AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel];
685  if (AdapterObject != NULL)
686  {
687  if (AdapterObject->NeedsMapRegisters &&
688  MapRegisters > AdapterObject->MapRegistersPerChannel)
689  AdapterObject->MapRegistersPerChannel = MapRegisters;
690  }
691  }
692 
693  if (AdapterObject == NULL)
694  {
695  AdapterObject = HalpDmaAllocateChildAdapter(
696  MapRegisters, DeviceDescription);
697  if (AdapterObject == NULL)
698  {
699  KeSetEvent(&HalpDmaLock, 0, 0);
700  return NULL;
701  }
702 
703  if (EisaAdapter)
704  {
705  HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject;
706  }
707 
708  if (MapRegisters > 0)
709  {
710  AdapterObject->NeedsMapRegisters = TRUE;
711  MasterAdapter = HalpMasterAdapter;
712  AdapterObject->MapRegistersPerChannel = MapRegisters;
713 
714  /*
715  * FIXME: Verify that the following makes sense. Actually
716  * MasterAdapter->NumberOfMapRegisters contains even the number
717  * of gaps, so this will not work correctly all the time. It
718  * doesn't matter much since it's only optimization to avoid
719  * queuing work items in HalAllocateAdapterChannel.
720  */
721 
722  MasterAdapter->CommittedMapRegisters += MapRegisters;
723  if (MasterAdapter->CommittedMapRegisters > MasterAdapter->NumberOfMapRegisters)
724  HalpGrowMapBuffers(MasterAdapter, 0x10000);
725  }
726  else
727  {
728  AdapterObject->NeedsMapRegisters = FALSE;
730  AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1;
731  else
732  AdapterObject->MapRegistersPerChannel = 1;
733  }
734  }
735 
736  if (!EisaAdapter)
737  InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList);
738 
739  /*
740  * Release the DMA lock. HalpDmaAdapterList and HalpEisaAdapter will
741  * no longer be touched, so we don't need it.
742  */
743 
744  KeSetEvent(&HalpDmaLock, 0, 0);
745 
746  /*
747  * Setup the values in the adapter object that are common for all
748  * types of buses.
749  */
750 
752  AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount;
753  else
754  AdapterObject->IgnoreCount = 0;
755 
756  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
757  AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses;
758  AdapterObject->ScatterGather = DeviceDescription->ScatterGather;
759  AdapterObject->MasterDevice = DeviceDescription->Master;
760  *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel;
761 
762  /*
763  * For non-(E)ISA adapters we have already done all the work. On the
764  * other hand for (E)ISA adapters we must still setup the DMA modes
765  * and prepare the controller.
766  */
767 
768  if (EisaAdapter)
769  {
770  if (!HalpDmaInitializeEisaAdapter(AdapterObject, DeviceDescription))
771  {
772  ObDereferenceObject(AdapterObject);
773  return NULL;
774  }
775  }
776 
777  return AdapterObject;
778 }
static LIST_ENTRY HalpDmaAdapterList
Definition: dma.c:78
#define TRUE
Definition: types.h:120
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
#define MAXLONG
Definition: umtypes.h:116
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define InsertTailList(ListHead, Entry)
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
static PADAPTER_OBJECT HalpEisaAdapter[8]
Definition: dma.c:79
BOOLEAN NTAPI HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject, IN ULONG SizeOfMapBuffers)
Definition: dma.c:203
BOOLEAN IgnoreCount
Definition: iotypes.h:2031
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
BOOLEAN Dma32BitAddresses
Definition: iotypes.h:2030
BOOLEAN Dma64BitAddresses
Definition: iotypes.h:2033
_Must_inspect_result_ _In_ PDEVICE_DESCRIPTION DeviceDescription
Definition: iofuncs.h:1015
BOOLEAN ScatterGather
Definition: iotypes.h:2027
#define BYTES_TO_PAGES(Size)
BOOLEAN NTAPI HalpDmaInitializeEisaAdapter(PADAPTER_OBJECT AdapterObject, PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:461
UnicodeString MaximumLength
Definition: rtlfuncs.h:2982
static KEVENT HalpDmaLock
Definition: dma.c:77
#define DEVICE_DESCRIPTION_VERSION2
Definition: iotypes.h:2022
INTERFACE_TYPE InterfaceType
Definition: iotypes.h:2036
unsigned int ULONG
Definition: retypes.h:1
static PADAPTER_OBJECT HalpMasterAdapter
Definition: dma.c:81
PADAPTER_OBJECT NTAPI HalpDmaAllocateChildAdapter(ULONG NumberOfMapRegisters, PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:391
#define DEVICE_DESCRIPTION_VERSION1
Definition: iotypes.h:2021

◆ HalpCopyBufferMap()

VOID NTAPI HalpCopyBufferMap ( PMDL  Mdl,
PROS_MAP_REGISTER_ENTRY  MapRegisterBase,
PVOID  CurrentVa,
ULONG  Length,
BOOLEAN  WriteToDevice 
)

Definition at line 1468 of file dma.c.

1474 {
1475  ULONG CurrentLength;
1476  ULONG_PTR CurrentAddress;
1477  ULONG ByteOffset;
1479 
1481  if (VirtualAddress == NULL)
1482  {
1483  /*
1484  * NOTE: On real NT a mechanism with reserved pages is implemented
1485  * to handle this case in a slow, but graceful non-fatal way.
1486  */
1487  KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0);
1488  }
1489 
1490  CurrentAddress = (ULONG_PTR)VirtualAddress +
1491  (ULONG_PTR)CurrentVa -
1493 
1494  while (Length > 0)
1495  {
1496  ByteOffset = BYTE_OFFSET(CurrentAddress);
1497  CurrentLength = PAGE_SIZE - ByteOffset;
1498  if (CurrentLength > Length)
1499  CurrentLength = Length;
1500 
1501  if (WriteToDevice)
1502  {
1503  RtlCopyMemory(
1504  (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1505  (PVOID)CurrentAddress,
1506  CurrentLength);
1507  }
1508  else
1509  {
1510  RtlCopyMemory(
1511  (PVOID)CurrentAddress,
1512  (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1513  CurrentLength);
1514  }
1515 
1516  Length -= CurrentLength;
1517  CurrentAddress += CurrentLength;
1518  MapRegisterBase++;
1519  }
1520 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define MmGetMdlVirtualAddress(_Mdl)
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
uint32_t ULONG_PTR
Definition: typedefs.h:64
smooth NULL
Definition: ftsmooth.c:416
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3791
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:189
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
#define BYTE_OFFSET(Va)
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:107
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:716

Referenced by IoFlushAdapterBuffers(), and IoMapTransfer().

◆ HalpDmaAllocateChildAdapter()

PADAPTER_OBJECT NTAPI HalpDmaAllocateChildAdapter ( ULONG  NumberOfMapRegisters,
PDEVICE_DESCRIPTION  DeviceDescription 
)

Definition at line 391 of file dma.c.

394 {
395  PADAPTER_OBJECT AdapterObject;
398  HANDLE Handle;
399 
402  NULL,
404  NULL,
405  NULL);
406 
408  KernelMode,
411  KernelMode,
412  NULL,
413  sizeof(ADAPTER_OBJECT),
414  0,
415  0,
416  (PVOID)&AdapterObject);
417  if (!NT_SUCCESS(Status))
418  return NULL;
419 
421  AdapterObject,
424  KernelMode);
425  if (!NT_SUCCESS(Status))
426  return NULL;
427 
428  RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
429 
431  AdapterObject,
432  NULL,
434  0,
435  NULL,
436  &Handle);
437  if (!NT_SUCCESS(Status))
438  return NULL;
439 
440  ZwClose(Handle);
441 
442  AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version;
443  AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT);
444  AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations;
445  AdapterObject->MapRegistersPerChannel = 1;
446  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
447  AdapterObject->ChannelNumber = 0xFF;
448  AdapterObject->MasterAdapter = HalpMasterAdapter;
449  KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
450 
451  return AdapterObject;
452 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
LONG NTSTATUS
Definition: precomp.h:26
static DMA_OPERATIONS HalpDmaOperations
Definition: dma.c:94
VOID NTAPI KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:22
USHORT Size
Definition: iotypes.h:2186
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
struct _DMA_OPERATIONS * DmaOperations
Definition: iotypes.h:2187
#define FILE_READ_DATA
Definition: nt_native.h:628
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:383
#define FILE_WRITE_DATA
Definition: nt_native.h:631
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:952
BOOLEAN Dma32BitAddresses
Definition: iotypes.h:2030
_Must_inspect_result_ _In_ PDEVICE_DESCRIPTION DeviceDescription
Definition: iofuncs.h:1015
_In_ HANDLE Handle
Definition: extypes.h:390
USHORT Version
Definition: iotypes.h:2185
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
POBJECT_TYPE IoAdapterObjectType
Definition: adapter.c:18
#define OBJ_PERMANENT
Definition: winternl.h:226
Status
Definition: gdiplustypes.h:24
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2932
unsigned short USHORT
Definition: pedump.c:61
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
static PADAPTER_OBJECT HalpMasterAdapter
Definition: dma.c:81
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106

Referenced by HalGetAdapter().

◆ HalpDmaAllocateMasterAdapter()

PADAPTER_OBJECT NTAPI HalpDmaAllocateMasterAdapter ( VOID  )

Definition at line 332 of file dma.c.

333 {
334  PADAPTER_OBJECT MasterAdapter;
335  ULONG Size, SizeOfBitmap;
336 
337  SizeOfBitmap = MAX_MAP_REGISTERS;
338  Size = sizeof(ADAPTER_OBJECT);
339  Size += sizeof(RTL_BITMAP);
340  Size += (SizeOfBitmap + 7) >> 3;
341 
342  MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA);
343  if (MasterAdapter == NULL)
344  return NULL;
345 
346  RtlZeroMemory(MasterAdapter, Size);
347 
348  KeInitializeSpinLock(&MasterAdapter->SpinLock);
349  InitializeListHead(&MasterAdapter->AdapterQueue);
350 
351  MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1);
353  MasterAdapter->MapRegisters,
354  (PULONG)(MasterAdapter->MapRegisters + 1),
355  SizeOfBitmap);
356  RtlSetAllBits(MasterAdapter->MapRegisters);
357  MasterAdapter->NumberOfMapRegisters = 0;
358  MasterAdapter->CommittedMapRegisters = 0;
359 
360  MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(
361  NonPagedPool,
362  SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY),
363  TAG_DMA);
364  if (MasterAdapter->MapRegisterBase == NULL)
365  {
366  ExFreePool(MasterAdapter);
367  return NULL;
368  }
369 
370  RtlZeroMemory(MasterAdapter->MapRegisterBase,
371  SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY));
372  if (!HalpGrowMapBuffers(MasterAdapter, 0x10000))
373  {
374  ExFreePool(MasterAdapter);
375  return NULL;
376  }
377 
378  return MasterAdapter;
379 }
struct _RTL_BITMAP RTL_BITMAP
struct _ADAPTER_OBJECT ADAPTER_OBJECT
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
Definition: haldma.h:312
BOOLEAN NTAPI HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject, IN ULONG SizeOfMapBuffers)
Definition: dma.c:203
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:238
smooth NULL
Definition: ftsmooth.c:416
void * PVOID
Definition: retypes.h:9
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TAG_DMA
Definition: dma.c:116
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define MAX_MAP_REGISTERS
Definition: dma.c:114
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
unsigned int * PULONG
Definition: retypes.h:1
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by HalpInitDma().

◆ HalpDmaGetDmaAlignment()

ULONG NTAPI HalpDmaGetDmaAlignment ( PADAPTER_OBJECT  AdapterObject)

Definition at line 918 of file dma.c.

920 {
921  return 1;
922 }

◆ HalpDmaInitializeEisaAdapter()

BOOLEAN NTAPI HalpDmaInitializeEisaAdapter ( PADAPTER_OBJECT  AdapterObject,
PDEVICE_DESCRIPTION  DeviceDescription 
)

Definition at line 461 of file dma.c.

464 {
465  UCHAR Controller;
466  DMA_MODE DmaMode = {{0 }};
467  DMA_EXTENDED_MODE ExtendedMode = {{ 0 }};
468  PVOID AdapterBaseVa;
469 
470  Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1;
471 
472  if (Controller == 1)
473  AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController1);
474  else
475  AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController2);
476 
477  AdapterObject->AdapterNumber = Controller;
478  AdapterObject->ChannelNumber = (UCHAR)(DeviceDescription->DmaChannel & 3);
479  AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel];
480  AdapterObject->Width16Bits = FALSE;
481  AdapterObject->AdapterBaseVa = AdapterBaseVa;
482 
483  if (HalpEisaDma)
484  {
485  ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber;
486 
487  switch (DeviceDescription->DmaSpeed)
488  {
489  case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break;
490  case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break;
491  case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break;
492  case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break;
493  default:
494  return FALSE;
495  }
496 
497  switch (DeviceDescription->DmaWidth)
498  {
499  case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break;
500  case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break;
501  case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break;
502  default:
503  return FALSE;
504  }
505 
506  if (Controller == 1)
507  WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode1),
508  ExtendedMode.Byte);
509  else
510  WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode2),
511  ExtendedMode.Byte);
512  }
513  else
514  {
515  /*
516  * Validate setup for non-busmaster DMA adapter. Secondary controller
517  * supports only 16-bit transfers and main controller supports only
518  * 8-bit transfers. Anything else is invalid.
519  */
520 
522  {
523  if (Controller == 2 && DeviceDescription->DmaWidth == Width16Bits)
524  AdapterObject->Width16Bits = TRUE;
525  else if (Controller != 1 || DeviceDescription->DmaWidth != Width8Bits)
526  return FALSE;
527  }
528  }
529 
530  DmaMode.Channel = AdapterObject->ChannelNumber;
532 
533  /*
534  * Set the DMA request mode.
535  *
536  * For (E)ISA bus master devices just unmask (enable) the DMA channel
537  * and set it to cascade mode. Otherwise just select the right one
538  * bases on the passed device description.
539  */
540 
542  {
544  if (Controller == 1)
545  {
546  /* Set the Request Data */
547  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode,
548  DmaMode.Byte);
549  /* Unmask DMA Channel */
550  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask,
551  AdapterObject->ChannelNumber | DMA_CLEARMASK);
552  } else {
553  /* Set the Request Data */
554  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode,
555  DmaMode.Byte);
556  /* Unmask DMA Channel */
557  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask,
558  AdapterObject->ChannelNumber | DMA_CLEARMASK);
559  }
560  }
561  else
562  {
565  else
567  }
568 
569  AdapterObject->AdapterMode = DmaMode;
570 
571  return TRUE;
572 }
#define TYPE_A_TIMING
Definition: haldma.h:150
UCHAR AutoInitialize
Definition: haldma.h:95
#define TRUE
Definition: types.h:120
#define B_32BITS
Definition: haldma.h:145
_In_ ULONG Mode
Definition: hubbusif.h:303
unsigned char * PUCHAR
Definition: retypes.h:3
DMA_SPEED DmaSpeed
Definition: iotypes.h:2038
#define TypeA
Definition: nslookup.h:13
#define BURST_TIMING
Definition: haldma.h:152
#define DMA_CLEARMASK
Definition: haldma.h:175
UCHAR Byte
Definition: haldma.h:99
UCHAR Channel
Definition: haldma.h:93
static BOOLEAN HalpEisaDma
Definition: dma.c:80
void * PVOID
Definition: retypes.h:9
#define B_16BITS
Definition: haldma.h:146
_Must_inspect_result_ _In_ PDEVICE_DESCRIPTION DeviceDescription
Definition: iofuncs.h:1015
#define COMPATIBLE_TIMING
Definition: haldma.h:149
if(!(yy_init))
Definition: macro.lex.yy.c:714
BOOLEAN DemandMode
Definition: iotypes.h:2028
DMA_WIDTH DmaWidth
Definition: iotypes.h:2037
unsigned char UCHAR
Definition: xmlstorage.h:181
UCHAR ChannelNumber
Definition: haldma.h:133
UCHAR RequestMode
Definition: haldma.h:97
UCHAR TransferSize
Definition: haldma.h:134
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
static const ULONG_PTR HalpEisaPortPage[8]
Definition: dma.c:83
#define SINGLE_REQUEST_MODE
Definition: haldma.h:170
#define TYPE_B_TIMING
Definition: haldma.h:151
#define DEMAND_REQUEST_MODE
Definition: haldma.h:169
void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value)
Definition: mach.c:532
#define B_8BITS
Definition: haldma.h:143
#define CASCADE_REQUEST_MODE
Definition: haldma.h:172
BOOLEAN AutoInitialize
Definition: iotypes.h:2029
UCHAR TimingMode
Definition: haldma.h:135

Referenced by HalGetAdapter().

◆ HalpGetAdapterMaximumPhysicalAddress()

PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 167 of file dma.c.

169 {
170  PHYSICAL_ADDRESS HighestAddress;
171 
172  if (AdapterObject->MasterDevice)
173  {
174  if (AdapterObject->Dma64BitAddresses)
175  {
176  HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
177  return HighestAddress;
178  }
179  else if (AdapterObject->Dma32BitAddresses)
180  {
181  HighestAddress.QuadPart = 0xFFFFFFFF;
182  return HighestAddress;
183  }
184  }
185 
186  HighestAddress.QuadPart = 0xFFFFFF;
187  return HighestAddress;
188 }
#define ULL(a, b)
Definition: format_msg.c:27
LONGLONG QuadPart
Definition: typedefs.h:113

Referenced by HalAllocateCommonBuffer(), HalpGrowMapBuffers(), IoFlushAdapterBuffers(), and IoMapTransfer().

◆ HalpGetDmaAdapter()

PDMA_ADAPTER NTAPI HalpGetDmaAdapter ( IN PVOID  Context,
IN PDEVICE_DESCRIPTION  DeviceDescription,
OUT PULONG  NumberOfMapRegisters 
)

Definition at line 790 of file dma.c.

794 {
796 }
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
_Must_inspect_result_ _In_ PDEVICE_DESCRIPTION DeviceDescription
Definition: iofuncs.h:1015
PADAPTER_OBJECT NTAPI HalGetAdapter(IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
Definition: dma.c:22

Referenced by HalInitSystem(), and HalpInitDma().

◆ HalpGrowMapBuffers()

BOOLEAN NTAPI HalpGrowMapBuffers ( IN PADAPTER_OBJECT  AdapterObject,
IN ULONG  SizeOfMapBuffers 
)

Definition at line 203 of file dma.c.

206 {
211  PHYSICAL_ADDRESS BoundryAddressMultiple;
212  KIRQL OldIrql;
213  ULONG MapRegisterCount;
214 
215  /* FIXME: Check if enough map register slots are available. */
216 
217  MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers);
218 
219  /*
220  * Allocate memory for the new map registers. For 32-bit adapters we use
221  * two passes in order not to waste scare resource (low memory).
222  */
223 
228  HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0;
229  BoundryAddressMultiple.QuadPart = 0;
230 
232  MapRegisterCount << PAGE_SHIFT, LowestAcceptableAddress,
233  HighestAcceptableAddress, BoundryAddressMultiple, MmNonCached);
234 
236  {
239  MapRegisterCount << PAGE_SHIFT, LowestAcceptableAddress,
240  HighestAcceptableAddress, BoundryAddressMultiple, MmNonCached);
241  }
242 
243  if (VirtualAddress == NULL)
244  return FALSE;
245 
247 
248  /*
249  * All the following must be done with the master adapter lock held
250  * to prevent corruption.
251  */
252 
253  OldIrql = KfAcquireSpinLock(&AdapterObject->SpinLock);
254 
255  /*
256  * Setup map register entries for the buffer allocated. Each entry has
257  * a virtual and physical address and corresponds to PAGE_SIZE large
258  * buffer.
259  */
260 
261  if (MapRegisterCount > 0)
262  {
263  PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry;
264 
265  CurrentEntry = AdapterObject->MapRegisterBase +
266  AdapterObject->NumberOfMapRegisters;
267  do
268  {
269  /*
270  * Leave one entry free for every non-contiguous memory region
271  * in the map register bitmap. This ensures that we can search
272  * using RtlFindClearBits for contiguous map register regions.
273  *
274  * Also for non-EISA DMA leave one free entry for every 64Kb
275  * break, because the DMA controller can handle only coniguous
276  * 64Kb regions.
277  */
278 
279  if (CurrentEntry != AdapterObject->MapRegisterBase)
280  {
281  PreviousEntry = CurrentEntry - 1;
282  if (PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE ==
284  {
285  if (!HalpEisaDma)
286  {
287  if ((PreviousEntry->PhysicalAddress.LowPart ^
288  PhysicalAddress.LowPart) & 0xFFFF0000)
289  {
290  CurrentEntry++;
291  AdapterObject->NumberOfMapRegisters++;
292  }
293  }
294  }
295  else
296  {
297  CurrentEntry++;
298  AdapterObject->NumberOfMapRegisters++;
299  }
300  }
301 
302  RtlClearBit(AdapterObject->MapRegisters,
303  CurrentEntry - AdapterObject->MapRegisterBase);
304  CurrentEntry->VirtualAddress = VirtualAddress;
305  CurrentEntry->PhysicalAddress = PhysicalAddress;
306 
309 
310  CurrentEntry++;
311  AdapterObject->NumberOfMapRegisters++;
312  MapRegisterCount--;
313  }
314  while (MapRegisterCount != 0);
315  }
316 
317  KfReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
318 
319  return TRUE;
320 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define TRUE
Definition: types.h:120
Definition: haldma.h:312
PVOID VirtualAddress
Definition: haldma.h:314
uint32_t ULONG_PTR
Definition: typedefs.h:64
UCHAR KIRQL
Definition: env_spec_w32.h:591
PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:167
smooth NULL
Definition: ftsmooth.c:416
static BOOLEAN HalpEisaDma
Definition: dma.c:80
void * PVOID
Definition: retypes.h:9
VOID FASTCALL KfReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL OldIrql)
Definition: spinlock.c:96
VOID NTAPI RtlClearBit(_In_ PRTL_BITMAP BitMapHeader, _In_ BITMAP_INDEX BitNumber)
Definition: bitmap.c:294
#define BYTES_TO_PAGES(Size)
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1061
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
PHYSICAL_ADDRESS PhysicalAddress
Definition: haldma.h:315
_Out_ PNDIS_HANDLE _Out_ PUINT _In_ PNDIS_STRING _In_ NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
Definition: ndis.h:3227
ULONG LowPart
Definition: typedefs.h:105
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3791
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS LowestAcceptableAddress
Definition: mmfuncs.h:214
KIRQL FASTCALL KfAcquireSpinLock(PKSPIN_LOCK SpinLock)
Definition: spinlock.c:85
unsigned int ULONG
Definition: retypes.h:1
PHYSICAL_ADDRESS NTAPI MmGetPhysicalAddress(IN PVOID Address)
Definition: stubs.c:682
LONGLONG QuadPart
Definition: typedefs.h:113
PVOID NTAPI MmAllocateContiguousMemorySpecifyCache(IN SIZE_T NumberOfBytes, IN PHYSICAL_ADDRESS LowestAcceptableAddress OPTIONAL, IN PHYSICAL_ADDRESS HighestAcceptableAddress, IN PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL, IN MEMORY_CACHING_TYPE CacheType OPTIONAL)
Definition: contmem.c:574

Referenced by HalGetAdapter(), HalpDmaAllocateMasterAdapter(), and HalpGrowMapBufferWorker().

◆ HalpGrowMapBufferWorker()

VOID NTAPI HalpGrowMapBufferWorker ( PVOID  DeferredContext)

Definition at line 1005 of file dma.c.

1006 {
1008  KIRQL OldIrql;
1009  BOOLEAN Succeeded;
1010 
1011  /*
1012  * Try to allocate new map registers for the adapter.
1013  *
1014  * NOTE: The NT implementation actually tries to allocate more map
1015  * registers than needed as an optimization.
1016  */
1017 
1019  FALSE, NULL);
1020  Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter,
1021  WorkItem->NumberOfMapRegisters);
1022  KeSetEvent(&HalpDmaLock, 0, 0);
1023 
1024  if (Succeeded)
1025  {
1026  /*
1027  * Flush the adapter queue now that new map registers are ready. The
1028  * easiest way to do that is to call IoFreeMapRegisters to not free
1029  * any registers. Note that we use the magic (PVOID)2 map register
1030  * base to bypass the parameter checking.
1031  */
1032 
1034  IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
1036  }
1037 
1038  ExFreePool(WorkItem);
1039 }
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
VOID NTAPI IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject, IN PVOID MapRegisterBase, IN ULONG NumberOfMapRegisters)
Definition: dma.c:114
UCHAR KIRQL
Definition: env_spec_w32.h:591
PADAPTER_OBJECT AdapterObject
Definition: haldma.h:363
struct _GROW_WORK_ITEM * PGROW_WORK_ITEM
BOOLEAN NTAPI HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject, IN ULONG SizeOfMapBuffers)
Definition: dma.c:203
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
static KEVENT HalpDmaLock
Definition: dma.c:77
ULONG NumberOfMapRegisters
Definition: haldma.h:364
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675

Referenced by HalAllocateAdapterChannel().

◆ HalpInitDma()

VOID HalpInitDma ( VOID  )

Definition at line 121 of file dma.c.

122 {
123  /*
124  * Initialize the DMA Operation table
125  */
131 
132  /*
133  * Check if Extended DMA is available. We're just going to do a random
134  * read and write.
135  */
136 
137  WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2), 0x2A);
138  if (READ_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)) == 0x2A)
139  HalpEisaDma = TRUE;
140 
141  /*
142  * Intialize all the global variables and allocate master adapter with
143  * first map buffers.
144  */
145 
148 
150 
151  /*
152  * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's
153  * used by IoGetDmaAdapter in the kernel.
154  */
155 
157 }
static LIST_ENTRY HalpDmaAdapterList
Definition: dma.c:78
#define HalGetDmaAdapter
Definition: haltypes.h:291
#define TRUE
Definition: types.h:120
PHYSICAL_ADDRESS NTAPI IoMapTransfer(IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN OUT PULONG Length, IN BOOLEAN WriteToDevice)
Definition: dma.c:144
PFREE_MAP_REGISTERS FreeMapRegisters
Definition: iotypes.h:2317
unsigned char * PUCHAR
Definition: retypes.h:3
UCHAR NTAPI READ_PORT_UCHAR(PUCHAR Address)
Definition: mach.c:528
static DMA_OPERATIONS HalpDmaOperations
Definition: dma.c:94
BOOLEAN(NTAPI * PFLUSH_ADAPTER_BUFFERS)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PMDL Mdl, _In_ PVOID MapRegisterBase, _In_ PVOID CurrentVa, _In_ ULONG Length, _In_ BOOLEAN WriteToDevice)
Definition: iotypes.h:2218
VOID NTAPI IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject, IN PVOID MapRegisterBase, IN ULONG NumberOfMapRegisters)
Definition: dma.c:114
VOID(NTAPI * PFREE_ADAPTER_CHANNEL)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2227
NTSTATUS(NTAPI * PALLOCATE_ADAPTER_CHANNEL)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG NumberOfMapRegisters, _In_ PDRIVER_CONTROL ExecutionRoutine, _In_ PVOID Context)
Definition: iotypes.h:2210
PMAP_TRANSFER MapTransfer
Definition: iotypes.h:2318
static BOOLEAN HalpEisaDma
Definition: dma.c:80
VOID NTAPI IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:103
PFLUSH_ADAPTER_BUFFERS FlushAdapterBuffers
Definition: iotypes.h:2315
PHYSICAL_ADDRESS(NTAPI * PMAP_TRANSFER)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PMDL Mdl, _In_ PVOID MapRegisterBase, _In_ PVOID CurrentVa, _Inout_ PULONG Length, _In_ BOOLEAN WriteToDevice)
Definition: iotypes.h:2237
NTSTATUS NTAPI IoAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_OBJECT DeviceObject, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine, IN PVOID Context)
Definition: adapter.c:30
PFREE_ADAPTER_CHANNEL FreeAdapterChannel
Definition: iotypes.h:2316
BOOLEAN NTAPI IoFlushAdapterBuffers(IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice)
Definition: dma.c:127
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
PALLOCATE_ADAPTER_CHANNEL AllocateAdapterChannel
Definition: iotypes.h:2314
PDMA_ADAPTER NTAPI HalpGetDmaAdapter(IN PVOID Context, IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
Definition: dma.c:790
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
static KEVENT HalpDmaLock
Definition: dma.c:77
VOID(NTAPI * PFREE_MAP_REGISTERS)(_In_ PDMA_ADAPTER DmaAdapter, PVOID MapRegisterBase, ULONG NumberOfMapRegisters)
Definition: iotypes.h:2231
void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value)
Definition: mach.c:532
static PADAPTER_OBJECT HalpMasterAdapter
Definition: dma.c:81
PADAPTER_OBJECT NTAPI HalpDmaAllocateMasterAdapter(VOID)
Definition: dma.c:332

Referenced by HalInitSystem(), and HalpInitPhase1().

◆ HalPutDmaAdapter()

VOID NTAPI HalPutDmaAdapter ( PADAPTER_OBJECT  AdapterObject)

Definition at line 808 of file dma.c.

810 {
811  if (AdapterObject->ChannelNumber == 0xFF)
812  {
814  FALSE, NULL);
815  RemoveEntryList(&AdapterObject->AdapterList);
816  KeSetEvent(&HalpDmaLock, 0, 0);
817  }
818 
819  ObDereferenceObject(AdapterObject);
820 }
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
smooth NULL
Definition: ftsmooth.c:416
static KEVENT HalpDmaLock
Definition: dma.c:77

◆ HalReadDmaCounter()

ULONG NTAPI HalReadDmaCounter ( PADAPTER_OBJECT  AdapterObject)

Definition at line 933 of file dma.c.

935 {
936  KIRQL OldIrql;
937  ULONG Count, OldCount;
938 
939  ASSERT(!AdapterObject->MasterDevice);
940 
941  /*
942  * Acquire the master adapter lock since we're going to mess with the
943  * system DMA controller registers and we really don't want anyone
944  * to do the same at the same time.
945  */
946 
947  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
948 
949  /* Send the request to the specific controller. */
950  if (AdapterObject->AdapterNumber == 1)
951  {
952  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
953 
954  Count = 0xffff00;
955  do
956  {
957  OldCount = Count;
958  /* Send Reset */
959  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
960  /* Read Count */
961  Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
962  [AdapterObject->ChannelNumber].DmaBaseCount);
963  Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
964  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
965  }
966  while (0xffff00 & (OldCount ^ Count));
967  }
968  else
969  {
970  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
971 
972  Count = 0xffff00;
973  do
974  {
975  OldCount = Count;
976  /* Send Reset */
977  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
978  /* Read Count */
979  Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
980  [AdapterObject->ChannelNumber].DmaBaseCount);
981  Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
982  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
983  }
984  while (0xffff00 & (OldCount ^ Count));
985  }
986 
987  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
988 
989  Count++;
990  Count &= 0xffff;
991  if (AdapterObject->Width16Bits)
992  Count *= 2;
993 
994  return Count;
995 }
UCHAR DmaBaseCount
Definition: haldma.h:184
DMA1_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:197
UCHAR NTAPI READ_PORT_UCHAR(PUCHAR Address)
Definition: mach.c:528
DMA2_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:210
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
UCHAR KIRQL
Definition: env_spec_w32.h:591
UCHAR ClearBytePointer
Definition: haldma.h:219
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
UCHAR DmaBaseCount
Definition: haldma.h:191
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
unsigned int ULONG
Definition: retypes.h:1
void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value)
Definition: mach.c:532
UCHAR ClearBytePointer
Definition: haldma.h:202

◆ IoFlushAdapterBuffers()

BOOLEAN NTAPI IoFlushAdapterBuffers ( PADAPTER_OBJECT  AdapterObject,
PMDL  Mdl,
PVOID  MapRegisterBase,
PVOID  CurrentVa,
ULONG  Length,
BOOLEAN  WriteToDevice 
)

Definition at line 1555 of file dma.c.

1562 {
1563  BOOLEAN SlaveDma = FALSE;
1564  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1567  PPFN_NUMBER MdlPagesPtr;
1568 
1570 
1571  if (AdapterObject != NULL && !AdapterObject->MasterDevice)
1572  {
1573  /* Mask out (disable) the DMA channel. */
1574  if (AdapterObject->AdapterNumber == 1)
1575  {
1576  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1577  WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
1578  AdapterObject->ChannelNumber | DMA_SETMASK);
1579  }
1580  else
1581  {
1582  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1583  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
1584  AdapterObject->ChannelNumber | DMA_SETMASK);
1585  }
1586  SlaveDma = TRUE;
1587  }
1588 
1589  /* This can happen if the device supports hardware scatter/gather. */
1590  if (MapRegisterBase == NULL)
1591  return TRUE;
1592 
1593  RealMapRegisterBase =
1595 
1596  if (!WriteToDevice)
1597  {
1599  {
1600  if (RealMapRegisterBase->Counter != MAXULONG)
1601  {
1602  if (SlaveDma && !AdapterObject->IgnoreCount)
1603  Length -= HalReadDmaCounter(AdapterObject);
1604  HalpCopyBufferMap(Mdl, RealMapRegisterBase, CurrentVa, Length, FALSE);
1605  }
1606  }
1607  else
1608  {
1609  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1610  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1611 
1612  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1613  PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa);
1614 
1617  HighestAcceptableAddress.QuadPart)
1618  {
1619  HalpCopyBufferMap(Mdl, RealMapRegisterBase, CurrentVa, Length, FALSE);
1620  }
1621  }
1622  }
1623 
1624  RealMapRegisterBase->Counter = 0;
1625 
1626  return TRUE;
1627 }
#define DMA_SETMASK
Definition: haldma.h:174
#define ASSERT_IRQL_LESS_OR_EQUAL(x)
Definition: debug.h:251
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define TRUE
Definition: types.h:120
ULONG NTAPI HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:76
#define MmGetMdlPfnArray(_Mdl)
UCHAR SingleMask
Definition: haldma.h:215
Definition: haldma.h:312
VOID NTAPI HalpCopyBufferMap(PMDL Mdl, PROS_MAP_REGISTER_ENTRY MapRegisterBase, PVOID CurrentVa, ULONG Length, BOOLEAN WriteToDevice)
Definition: dma.c:1468
uint32_t ULONG_PTR
Definition: typedefs.h:64
ULONG * PPFN_NUMBER
Definition: ke.h:8
UCHAR SingleMask
Definition: haldma.h:200
PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:167
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1061
_Out_ PNDIS_HANDLE _Out_ PUINT _In_ PNDIS_STRING _In_ NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
Definition: ndis.h:3227
#define MAXULONG
Definition: typedefs.h:251
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:189
void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value)
Definition: mach.c:532
#define ULONG_PTR
Definition: config.h:101
#define MAP_BASE_SW_SG
Definition: haldma.h:367
#define BYTE_OFFSET(Va)
LONGLONG QuadPart
Definition: typedefs.h:113
ULONG Counter
Definition: haldma.h:316

◆ IoFreeAdapterChannel()

VOID NTAPI IoFreeAdapterChannel ( PADAPTER_OBJECT  AdapterObject)

Definition at line 1238 of file dma.c.

1240 {
1241  PADAPTER_OBJECT MasterAdapter;
1243  PWAIT_CONTEXT_BLOCK WaitContextBlock;
1244  ULONG Index = MAXULONG;
1245  ULONG Result;
1246  KIRQL OldIrql;
1247 
1248  MasterAdapter = AdapterObject->MasterAdapter;
1249 
1250  for (;;)
1251  {
1252  /*
1253  * To keep map registers, call here with AdapterObject->
1254  * NumberOfMapRegisters set to zero. This trick is used in
1255  * HalAllocateAdapterChannel for example.
1256  */
1257  if (AdapterObject->NumberOfMapRegisters)
1258  {
1260  AdapterObject,
1261  AdapterObject->MapRegisterBase,
1262  AdapterObject->NumberOfMapRegisters);
1263  }
1264 
1265  DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
1266  if (DeviceQueueEntry == NULL)
1267  {
1268  break;
1269  }
1270 
1271  WaitContextBlock = CONTAINING_RECORD(
1274  WaitQueueEntry);
1275 
1276  AdapterObject->CurrentWcb = WaitContextBlock;
1277  AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters;
1278 
1279  if (WaitContextBlock->NumberOfMapRegisters &&
1280  AdapterObject->MasterAdapter)
1281  {
1282  OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
1283 
1284  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1285  {
1287  MasterAdapter->MapRegisters,
1288  WaitContextBlock->NumberOfMapRegisters, 0);
1289  if (Index != MAXULONG)
1290  {
1291  AdapterObject->MapRegisterBase =
1292  MasterAdapter->MapRegisterBase + Index;
1293  if (!AdapterObject->ScatterGather)
1294  {
1295  AdapterObject->MapRegisterBase =
1297  (ULONG_PTR)AdapterObject->MapRegisterBase |
1298  MAP_BASE_SW_SG);
1299  }
1300  }
1301  }
1302 
1303  if (Index == MAXULONG)
1304  {
1305  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1306  KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1307  break;
1308  }
1309 
1310  KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1311  }
1312  else
1313  {
1314  AdapterObject->MapRegisterBase = NULL;
1315  AdapterObject->NumberOfMapRegisters = 0;
1316  }
1317 
1318  /* Call the adapter control routine. */
1319  Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(
1320  WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp,
1321  AdapterObject->MapRegisterBase, WaitContextBlock->DeviceContext);
1322 
1323  switch (Result)
1324  {
1325  case KeepObject:
1326  /*
1327  * We're done until the caller manually calls IoFreeAdapterChannel
1328  * or IoFreeMapRegisters.
1329  */
1330  return;
1331 
1333  /*
1334  * Hide the map registers so they aren't deallocated next time
1335  * around.
1336  */
1337  AdapterObject->NumberOfMapRegisters = 0;
1338  break;
1339 
1340  default:
1341  break;
1342  }
1343  }
1344 }
PDRIVER_CONTROL DeviceRoutine
Definition: iotypes.h:196
#define InsertTailList(ListHead, Entry)
VOID NTAPI IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject, IN PVOID MapRegisterBase, IN ULONG NumberOfMapRegisters)
Definition: dma.c:114
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint32_t ULONG_PTR
Definition: typedefs.h:64
UCHAR KIRQL
Definition: env_spec_w32.h:591
smooth NULL
Definition: ftsmooth.c:416
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
VOID FASTCALL KfReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL OldIrql)
Definition: spinlock.c:96
static const UCHAR Index[8]
Definition: usbohci.c:18
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define MAXULONG
Definition: typedefs.h:251
Definition: ketypes.h:566
PKDEVICE_QUEUE_ENTRY NTAPI KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:153
KIRQL FASTCALL KfAcquireSpinLock(PKSPIN_LOCK SpinLock)
Definition: spinlock.c:85
unsigned int ULONG
Definition: retypes.h:1
DRIVER_CONTROL * PDRIVER_CONTROL
Definition: iotypes.h:192
_Inout_ PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
Definition: kefuncs.h:339
#define MAP_BASE_SW_SG
Definition: haldma.h:367
ULONG NumberOfMapRegisters
Definition: iotypes.h:198

◆ IoFreeMapRegisters()

VOID NTAPI IoFreeMapRegisters ( IN PADAPTER_OBJECT  AdapterObject,
IN PVOID  MapRegisterBase,
IN ULONG  NumberOfMapRegisters 
)

Definition at line 1362 of file dma.c.

1366 {
1367  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
1368  PLIST_ENTRY ListEntry;
1369  KIRQL OldIrql;
1370  ULONG Index;
1371  ULONG Result;
1372 
1374 
1375  if (MasterAdapter == NULL || MapRegisterBase == NULL)
1376  return;
1377 
1378  OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
1379 
1380  if (NumberOfMapRegisters != 0)
1381  {
1382  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1383 
1384  RealMapRegisterBase =
1386  RtlClearBits(MasterAdapter->MapRegisters,
1387  RealMapRegisterBase - MasterAdapter->MapRegisterBase,
1389  }
1390 
1391  /*
1392  * Now that we freed few map registers it's time to look at the master
1393  * adapter queue and see if there is someone waiting for map registers.
1394  */
1395 
1396  while (!IsListEmpty(&MasterAdapter->AdapterQueue))
1397  {
1398  ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue);
1399  AdapterObject = CONTAINING_RECORD(
1400  ListEntry, struct _ADAPTER_OBJECT, AdapterQueue);
1401 
1403  MasterAdapter->MapRegisters,
1404  AdapterObject->NumberOfMapRegisters,
1405  MasterAdapter->NumberOfMapRegisters);
1406  if (Index == MAXULONG)
1407  {
1408  InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
1409  break;
1410  }
1411 
1412  KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1413 
1414  AdapterObject->MapRegisterBase =
1415  MasterAdapter->MapRegisterBase + Index;
1416  if (!AdapterObject->ScatterGather)
1417  {
1418  AdapterObject->MapRegisterBase =
1420  (ULONG_PTR)AdapterObject->MapRegisterBase |
1421  MAP_BASE_SW_SG);
1422  }
1423 
1424  Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(
1425  AdapterObject->CurrentWcb->DeviceObject,
1426  AdapterObject->CurrentWcb->CurrentIrp,
1427  AdapterObject->MapRegisterBase,
1428  AdapterObject->CurrentWcb->DeviceContext);
1429 
1430  switch (Result)
1431  {
1433  AdapterObject->NumberOfMapRegisters = 0;
1434  /* fall through */
1435 
1436  case DeallocateObject:
1437  if (AdapterObject->NumberOfMapRegisters)
1438  {
1439  OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
1440  RtlClearBits(MasterAdapter->MapRegisters,
1441  AdapterObject->MapRegisterBase -
1442  MasterAdapter->MapRegisterBase,
1443  AdapterObject->NumberOfMapRegisters);
1444  KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1445  }
1446  IoFreeAdapterChannel(AdapterObject);
1447  break;
1448 
1449  default:
1450  break;
1451  }
1452 
1453  OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
1454  }
1455 
1456  KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1457 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
Definition: haldma.h:312
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint32_t ULONG_PTR
Definition: typedefs.h:64
UCHAR KIRQL
Definition: env_spec_w32.h:591
smooth NULL
Definition: ftsmooth.c:416
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
VOID NTAPI IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:103
VOID FASTCALL KfReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL OldIrql)
Definition: spinlock.c:96
static const UCHAR Index[8]
Definition: usbohci.c:18
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
Definition: typedefs.h:118
#define MAXULONG
Definition: typedefs.h:251
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:189
KIRQL FASTCALL KfAcquireSpinLock(PKSPIN_LOCK SpinLock)
Definition: spinlock.c:85
unsigned int ULONG
Definition: retypes.h:1
DRIVER_CONTROL * PDRIVER_CONTROL
Definition: iotypes.h:192
#define MAP_BASE_SW_SG
Definition: haldma.h:367

◆ IoMapTransfer()

PHYSICAL_ADDRESS NTAPI IoMapTransfer ( IN PADAPTER_OBJECT  AdapterObject,
IN PMDL  Mdl,
IN PVOID  MapRegisterBase,
IN PVOID  CurrentVa,
IN OUT PULONG  Length,
IN BOOLEAN  WriteToDevice 
)

Definition at line 1662 of file dma.c.

1669 {
1670  PPFN_NUMBER MdlPagesPtr;
1671  PFN_NUMBER MdlPage1, MdlPage2;
1672  ULONG ByteOffset;
1673  ULONG TransferOffset;
1674  ULONG TransferLength;
1675  BOOLEAN UseMapRegisters;
1676  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1679  ULONG Counter;
1680  DMA_MODE AdapterMode;
1681  KIRQL OldIrql;
1682 
1683  /*
1684  * Precalculate some values that are used in all cases.
1685  *
1686  * ByteOffset is offset inside the page at which the transfer starts.
1687  * MdlPagesPtr is pointer inside the MDL page chain at the page where the
1688  * transfer start.
1689  * PhysicalAddress is physical address corresponding to the transfer
1690  * start page and offset.
1691  * TransferLength is the initial length of the transfer, which is reminder
1692  * of the first page. The actual value is calculated below.
1693  *
1694  * Note that all the variables can change during the processing which
1695  * takes place below. These are just initial values.
1696  */
1697 
1698  ByteOffset = BYTE_OFFSET(CurrentVa);
1699 
1700  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1701  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1702 
1703  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1705 
1706  TransferLength = PAGE_SIZE - ByteOffset;
1707 
1708  /*
1709  * Special case for bus master adapters with S/G support. We can directly
1710  * use the buffer specified by the MDL, so not much work has to be done.
1711  *
1712  * Just return the passed VA's corresponding physical address and update
1713  * length to the number of physically contiguous bytes found. Also
1714  * pages crossing the 4Gb boundary aren't considered physically contiguous.
1715  */
1716 
1717  if (MapRegisterBase == NULL)
1718  {
1719  while (TransferLength < *Length)
1720  {
1721  MdlPage1 = *MdlPagesPtr;
1722  MdlPage2 = *(MdlPagesPtr + 1);
1723  if (MdlPage1 + 1 != MdlPage2)
1724  break;
1725  if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF)
1726  break;
1727  TransferLength += PAGE_SIZE;
1728  MdlPagesPtr++;
1729  }
1730 
1731  if (TransferLength < *Length)
1732  *Length = TransferLength;
1733 
1734  return PhysicalAddress;
1735  }
1736 
1737  /*
1738  * The code below applies to slave DMA adapters and bus master adapters
1739  * without hardward S/G support.
1740  */
1741 
1742  RealMapRegisterBase =
1744 
1745  /*
1746  * Try to calculate the size of the transfer. We can only transfer
1747  * pages that are physically contiguous and that don't cross the
1748  * 64Kb boundary (this limitation applies only for ISA controllers).
1749  */
1750 
1751  while (TransferLength < *Length)
1752  {
1753  MdlPage1 = *MdlPagesPtr;
1754  MdlPage2 = *(MdlPagesPtr + 1);
1755  if (MdlPage1 + 1 != MdlPage2)
1756  break;
1757  if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF))
1758  break;
1759  TransferLength += PAGE_SIZE;
1760  MdlPagesPtr++;
1761  }
1762 
1763  if (TransferLength > *Length)
1764  TransferLength = *Length;
1765 
1766  /*
1767  * If we're about to simulate software S/G and not all the pages are
1768  * physically contiguous then we must use the map registers to store
1769  * the data and allow the whole transfer to proceed at once.
1770  */
1771 
1773  TransferLength < *Length)
1774  {
1775  UseMapRegisters = TRUE;
1776  PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
1778  TransferLength = *Length;
1779  RealMapRegisterBase->Counter = MAXULONG;
1780  Counter = 0;
1781  }
1782  else
1783  {
1784  /*
1785  * This is ordinary DMA transfer, so just update the progress
1786  * counters. These are used by IoFlushAdapterBuffers to track
1787  * the transfer progress.
1788  */
1789 
1790  UseMapRegisters = FALSE;
1791  Counter = RealMapRegisterBase->Counter;
1792  RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength);
1793 
1794  /*
1795  * Check if the buffer doesn't exceed the highest physical address
1796  * limit of the device. In that case we must use the map registers to
1797  * store the data.
1798  */
1799 
1801  if (PhysicalAddress.QuadPart + TransferLength >
1802  HighestAcceptableAddress.QuadPart)
1803  {
1804  UseMapRegisters = TRUE;
1805  PhysicalAddress = RealMapRegisterBase[Counter].PhysicalAddress;
1808  {
1809  RealMapRegisterBase->Counter = MAXULONG;
1810  Counter = 0;
1811  }
1812  }
1813  }
1814 
1815  /*
1816  * If we decided to use the map registers (see above) and we're about
1817  * to transfer data to the device then copy the buffers into the map
1818  * register memory.
1819  */
1820 
1821  if (UseMapRegisters && WriteToDevice)
1822  {
1823  HalpCopyBufferMap(Mdl, RealMapRegisterBase + Counter,
1824  CurrentVa, TransferLength, WriteToDevice);
1825  }
1826 
1827  /*
1828  * Return the length of transfer that actually takes place.
1829  */
1830 
1831  *Length = TransferLength;
1832 
1833  /*
1834  * If we're doing slave (system) DMA then program the (E)ISA controller
1835  * to actually start the transfer.
1836  */
1837 
1838  if (AdapterObject != NULL && !AdapterObject->MasterDevice)
1839  {
1840  AdapterMode = AdapterObject->AdapterMode;
1841 
1842  if (WriteToDevice)
1843  {
1844  AdapterMode.TransferType = WRITE_TRANSFER;
1845  }
1846  else
1847  {
1848  AdapterMode.TransferType = READ_TRANSFER;
1849  if (AdapterObject->IgnoreCount)
1850  {
1851  RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress +
1852  ByteOffset, TransferLength);
1853  }
1854  }
1855 
1856  TransferOffset = PhysicalAddress.LowPart & 0xFFFF;
1857  if (AdapterObject->Width16Bits)
1858  {
1859  TransferLength >>= 1;
1860  TransferOffset >>= 1;
1861  }
1862 
1863  OldIrql = KfAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock);
1864 
1865  if (AdapterObject->AdapterNumber == 1)
1866  {
1867  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1868 
1869  /* Reset Register */
1870  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
1871  /* Set the Mode */
1872  WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte);
1873  /* Set the Offset Register */
1874  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
1875  (UCHAR)(TransferOffset));
1876  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
1877  (UCHAR)(TransferOffset >> 8));
1878  /* Set the Page Register */
1879  WRITE_PORT_UCHAR(AdapterObject->PagePort +
1880  FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
1881  (UCHAR)(PhysicalAddress.LowPart >> 16));
1882  if (HalpEisaDma)
1883  {
1884  WRITE_PORT_UCHAR(AdapterObject->PagePort +
1885  FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
1886  0);
1887  }
1888  /* Set the Length */
1889  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
1890  (UCHAR)(TransferLength - 1));
1891  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
1892  (UCHAR)((TransferLength - 1) >> 8));
1893  /* Unmask the Channel */
1894  WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
1895  AdapterObject->ChannelNumber | DMA_CLEARMASK);
1896  }
1897  else
1898  {
1899  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1900 
1901  /* Reset Register */
1902  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
1903  /* Set the Mode */
1904  WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte);
1905  /* Set the Offset Register */
1906  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
1907  (UCHAR)(TransferOffset));
1908  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
1909  (UCHAR)(TransferOffset >> 8));
1910  /* Set the Page Register */
1911  WRITE_PORT_UCHAR(AdapterObject->PagePort +
1912  FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
1913  (UCHAR)(PhysicalAddress.u.LowPart >> 16));
1914  if (HalpEisaDma)
1915  {
1916  WRITE_PORT_UCHAR(AdapterObject->PagePort +
1917  FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
1918  0);
1919  }
1920  /* Set the Length */
1921  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
1922  (UCHAR)(TransferLength - 1));
1923  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
1924  (UCHAR)((TransferLength - 1) >> 8));
1925  /* Unmask the Channel */
1926  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
1927  AdapterObject->ChannelNumber | DMA_CLEARMASK);
1928  }
1929 
1930  KfReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
1931  }
1932 
1933  /*
1934  * Return physical address of the buffer with data that is used for the
1935  * transfer. It can either point inside the Mdl that was passed by the
1936  * caller or into the map registers if the Mdl buffer can't be used
1937  * directly.
1938  */
1939 
1940  return PhysicalAddress;
1941 }
UCHAR DmaBaseCount
Definition: haldma.h:184
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
UCHAR DmaBaseAddress
Definition: haldma.h:183
DMA1_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:197
#define TRUE
Definition: types.h:120
#define MmGetMdlPfnArray(_Mdl)
UCHAR SingleMask
Definition: haldma.h:215
UCHAR Mode
Definition: haldma.h:217
unsigned char * PUCHAR
Definition: retypes.h:3
UCHAR DmaBaseAddress
Definition: haldma.h:189
Definition: haldma.h:312
DMA2_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:210
#define DMA_CLEARMASK
Definition: haldma.h:175
UCHAR Byte
Definition: haldma.h:99
VOID NTAPI HalpCopyBufferMap(PMDL Mdl, PROS_MAP_REGISTER_ENTRY MapRegisterBase, PVOID CurrentVa, ULONG Length, BOOLEAN WriteToDevice)
Definition: dma.c:1468
uint32_t ULONG_PTR
Definition: typedefs.h:64
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG * PPFN_NUMBER
Definition: ke.h:8
UCHAR SingleMask
Definition: haldma.h:200
ULONG PFN_NUMBER
Definition: ke.h:8
PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:167
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
static BOOLEAN HalpEisaDma
Definition: dma.c:80
UCHAR ClearBytePointer
Definition: haldma.h:219
VOID FASTCALL KfReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL OldIrql)
Definition: spinlock.c:96
struct _LARGE_INTEGER::@2216 u
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define BYTES_TO_PAGES(Size)
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1061
unsigned char UCHAR
Definition: xmlstorage.h:181
UCHAR TransferType
Definition: haldma.h:94
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
UCHAR DmaBaseCount
Definition: haldma.h:191
PHYSICAL_ADDRESS PhysicalAddress
Definition: haldma.h:315
_Out_ PNDIS_HANDLE _Out_ PUINT _In_ PNDIS_STRING _In_ NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
Definition: ndis.h:3227
ULONG LowPart
Definition: typedefs.h:105
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3791
#define READ_TRANSFER
Definition: haldma.h:165
#define MAXULONG
Definition: typedefs.h:251
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:189
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
static LARGE_INTEGER Counter
Definition: clock.c:43
KIRQL FASTCALL KfAcquireSpinLock(PKSPIN_LOCK SpinLock)
Definition: spinlock.c:85
unsigned int ULONG
Definition: retypes.h:1
void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value)
Definition: mach.c:532
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
UCHAR Mode
Definition: haldma.h:201
#define WRITE_TRANSFER
Definition: haldma.h:166
#define MAP_BASE_SW_SG
Definition: haldma.h:367
UCHAR ClearBytePointer
Definition: haldma.h:202
#define BYTE_OFFSET(Va)
LONGLONG QuadPart
Definition: typedefs.h:113
ULONG Counter
Definition: haldma.h:316
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:716

Variable Documentation

◆ HalpDmaAdapterList

LIST_ENTRY HalpDmaAdapterList
static

Definition at line 78 of file dma.c.

Referenced by HalGetAdapter(), and HalpInitDma().

◆ HalpDmaLock

KEVENT HalpDmaLock
static

Definition at line 77 of file dma.c.

Referenced by HalGetAdapter(), HalpGrowMapBufferWorker(), HalpInitDma(), and HalPutDmaAdapter().

◆ HalpDmaOperations

DMA_OPERATIONS HalpDmaOperations
static
Initial value:
= {
sizeof(DMA_OPERATIONS),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL ,
NULL ,
NULL ,
NULL ,
}
PVOID(NTAPI * PALLOCATE_COMMON_BUFFER)(_In_ PDMA_ADAPTER DmaAdapter, _In_ ULONG Length, _Out_ PPHYSICAL_ADDRESS LogicalAddress, _In_ BOOLEAN CacheEnabled)
Definition: iotypes.h:2195
ULONG NTAPI HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:76
ULONG NTAPI HalpDmaGetDmaAlignment(PADAPTER_OBJECT AdapterObject)
Definition: dma.c:918
ULONG(NTAPI * PGET_DMA_ALIGNMENT)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2246
smooth NULL
Definition: ftsmooth.c:416
VOID(NTAPI * PFREE_COMMON_BUFFER)(_In_ PDMA_ADAPTER DmaAdapter, _In_ ULONG Length, _In_ PHYSICAL_ADDRESS LogicalAddress, _In_ PVOID VirtualAddress, _In_ BOOLEAN CacheEnabled)
Definition: iotypes.h:2202
VOID(NTAPI * PPUT_DMA_ADAPTER)(PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2191
struct _DMA_OPERATIONS DMA_OPERATIONS
VOID NTAPI HalPutDmaAdapter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:35
ULONG(NTAPI * PREAD_DMA_COUNTER)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2250
PVOID NTAPI HalAllocateCommonBuffer(IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PPHYSICAL_ADDRESS LogicalAddress, IN BOOLEAN CacheEnabled)
Definition: dma.c:46
VOID NTAPI HalFreeCommonBuffer(IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress, IN BOOLEAN CacheEnabled)
Definition: dma.c:61

Definition at line 94 of file dma.c.

Referenced by HalpDmaAllocateChildAdapter(), and HalpInitDma().

◆ HalpEisaAdapter

PADAPTER_OBJECT HalpEisaAdapter[8]
static

Definition at line 79 of file dma.c.

Referenced by HalGetAdapter().

◆ HalpEisaDma

BOOLEAN HalpEisaDma
static

Definition at line 80 of file dma.c.

Referenced by HalpDmaInitializeEisaAdapter(), HalpGrowMapBuffers(), HalpInitDma(), and IoMapTransfer().

◆ HalpEisaPortPage

const ULONG_PTR HalpEisaPortPage[8]
static
Initial value:
= {
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),
}
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255

Definition at line 83 of file dma.c.

Referenced by HalpDmaInitializeEisaAdapter().

◆ HalpMasterAdapter

PADAPTER_OBJECT HalpMasterAdapter
static

Definition at line 81 of file dma.c.

Referenced by HalGetAdapter(), HalpDmaAllocateChildAdapter(), and HalpInitDma().