ReactOS  0.4.15-dev-3428-g0609db5
dma.c File Reference
#include <hal.h>
#include <suppress.h>
#include <debug.h>
Include dependency graph for dma.c:

Go to the source code of this file.

Classes

struct  _SCATTER_GATHER_CONTEXT
 

Macros

#define NDEBUG
 
#define MAX_SG_ELEMENTS   0x10
 
#define MAX_MAP_REGISTERS   64
 
#define TAG_DMA   ' AMD'
 

Functions

VOID HalpInitDma (VOID)
 
HalPutScatterGatherList

Frees a scatter-gather list allocated from HalBuildScatterGatherList

Parameters
AdapterObjectAdapter object representing the bus master or system dma controller.
ScatterGatherThe scatter/gather list to be freed.
WriteToDeviceIndicates direction of DMA operation.
Returns
None
See also
HalBuildScatterGatherList

@implemented

NTSTATUS NTAPI HalCalculateScatterGatherListSize (IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl OPTIONAL, IN PVOID CurrentVa, IN ULONG Length, OUT PULONG ScatterGatherListSize, OUT PULONG pNumberOfMapRegisters)
 
VOID NTAPI HalPutScatterGatherList (IN PADAPTER_OBJECT AdapterObject, IN PSCATTER_GATHER_LIST ScatterGather, IN BOOLEAN WriteToDevice)
 
HalBuildScatterGatherList

Creates a scatter-gather list to be using in scatter/gather DMA

Parameters
AdapterObjectAdapter object representing the bus master or system dma controller.
DeviceObjectThe device target for DMA.
MdlThe MDL that describes the buffer to be mapped.
CurrentVaThe current VA in the buffer to be mapped for transfer.
LengthSpecifies the length of data in bytes to be mapped.
ExecutionRoutineA caller supplied AdapterListControl routine to be called when DMA is available.
ContextContext passed to the AdapterListControl routine.
WriteToDeviceIndicates direction of DMA operation.
ScatterGatherBufferUser buffer for the scatter-gather list
ScatterGatherBufferLengthBuffer length
Returns
The status of the operation.
See also
HalPutScatterGatherList

@implemented

NTSTATUS NTAPI HalBuildScatterGatherList (IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_OBJECT DeviceObject, IN PMDL Mdl, IN PVOID CurrentVa, IN ULONG Length, IN PDRIVER_LIST_CONTROL ExecutionRoutine, IN PVOID Context, IN BOOLEAN WriteToDevice, IN PVOID ScatterGatherBuffer, IN ULONG ScatterGatherLength)
 
NTSTATUS NTAPI HalBuildMdlFromScatterGatherList (IN PDMA_ADAPTER DmaAdapter, IN PSCATTER_GATHER_LIST ScatterGather, IN PMDL OriginalMdl, OUT PMDL *TargetMdl)
 
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 (IN ULONG NumberOfMapRegisters, IN PDEVICE_DESCRIPTION DeviceDescription)
 
HalpDmaInitializeEisaAdapter

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

BOOLEAN NTAPI HalpDmaInitializeEisaAdapter (IN PADAPTER_OBJECT AdapterObject, IN 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 (IN PDEVICE_DESCRIPTION DeviceDescription, OUT 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 (IN 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 (IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PPHYSICAL_ADDRESS LogicalAddress, IN BOOLEAN CacheEnabled)
 
HalGetScatterGatherList

Creates a scatter-gather list to be using in scatter/gather DMA

Parameters
AdapterObjectAdapter object representing the bus master or system dma controller.
DeviceObjectThe device target for DMA.
MdlThe MDL that describes the buffer to be mapped.
CurrentVaThe current VA in the buffer to be mapped for transfer.
LengthSpecifies the length of data in bytes to be mapped.
ExecutionRoutineA caller supplied AdapterListControl routine to be called when DMA is available.
ContextContext passed to the AdapterListControl routine.
WriteToDeviceIndicates direction of DMA operation.
Returns
The status of the operation.
See also
HalBuildScatterGatherList

@implemented

NTSTATUS NTAPI HalGetScatterGatherList (IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_OBJECT DeviceObject, IN PMDL Mdl, IN PVOID CurrentVa, IN ULONG Length, IN PDRIVER_LIST_CONTROL ExecutionRoutine, IN PVOID Context, IN BOOLEAN WriteToDevice)
 
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 (IN PADAPTER_OBJECT AdapterObject)
 
ULONG NTAPI HalReadDmaCounter (IN PADAPTER_OBJECT AdapterObject)
 
HalpGrowMapBufferWorker

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

VOID NTAPI HalpGrowMapBufferWorker (IN 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 (IN PADAPTER_OBJECT AdapterObject, IN PWAIT_CONTEXT_BLOCK WaitContextBlock, IN ULONG NumberOfMapRegisters, IN 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 (IN 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 (IN PMDL Mdl, IN PROS_MAP_REGISTER_ENTRY MapRegisterBase, IN PVOID CurrentVa, IN ULONG Length, IN 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 (IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN ULONG Length, IN 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 KSPIN_LOCK HalpDmaAdapterListLock
 
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
 

HalFreeCommonBuffer

Free common buffer allocated with HalAllocateCommonBuffer.

See also
HalAllocateCommonBuffer

@implemented

typedef struct _SCATTER_GATHER_CONTEXT SCATTER_GATHER_CONTEXT
 
typedef struct _SCATTER_GATHER_CONTEXTPSCATTER_GATHER_CONTEXT
 
VOID NTAPI HalFreeCommonBuffer (IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress, IN BOOLEAN CacheEnabled)
 
IO_ALLOCATION_ACTION NTAPI HalpScatterGatherAdapterControl (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context)
 

Macro Definition Documentation

◆ MAX_MAP_REGISTERS

#define MAX_MAP_REGISTERS   64

Definition at line 158 of file dma.c.

◆ MAX_SG_ELEMENTS

#define MAX_SG_ELEMENTS   0x10

Definition at line 80 of file dma.c.

◆ NDEBUG

#define NDEBUG

Definition at line 77 of file dma.c.

◆ TAG_DMA

#define TAG_DMA   ' AMD'

Definition at line 160 of file dma.c.

Typedef Documentation

◆ PSCATTER_GATHER_CONTEXT

◆ SCATTER_GATHER_CONTEXT

Function Documentation

◆ HalAllocateAdapterChannel()

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

Definition at line 1465 of file dma.c.

1469 {
1470  PADAPTER_OBJECT MasterAdapter;
1472  ULONG Index = MAXULONG;
1473  ULONG Result;
1474  KIRQL OldIrql;
1475 
1477 
1478  /* Set up the wait context block in case we can't run right away. */
1479  WaitContextBlock->DeviceRoutine = ExecutionRoutine;
1480  WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
1481 
1482  /* Returns true if queued, else returns false and sets the queue to busy */
1483  if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue,
1484  &WaitContextBlock->WaitQueueEntry))
1485  {
1486  return STATUS_SUCCESS;
1487  }
1488 
1489  MasterAdapter = AdapterObject->MasterAdapter;
1490 
1491  AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
1492  AdapterObject->CurrentWcb = WaitContextBlock;
1493 
1494  if ((NumberOfMapRegisters) && (AdapterObject->NeedsMapRegisters))
1495  {
1496  if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
1497  {
1498  AdapterObject->NumberOfMapRegisters = 0;
1499  IoFreeAdapterChannel(AdapterObject);
1501  }
1502 
1503  /*
1504  * Get the map registers. This is partly complicated by the fact
1505  * that new map registers can only be allocated at PASSIVE_LEVEL
1506  * and we're currently at DISPATCH_LEVEL. The following code has
1507  * two code paths:
1508  *
1509  * - If there is no adapter queued for map register allocation,
1510  * try to see if enough contiguous map registers are present.
1511  * In case they're we can just get them and proceed further.
1512  *
1513  * - If some adapter is already present in the queue we must
1514  * respect the order of adapters asking for map registers and
1515  * so the fast case described above can't take place.
1516  * This case is also entered if not enough coniguous map
1517  * registers are present.
1518  *
1519  * A work queue item is allocated and queued, the adapter is
1520  * also queued into the master adapter queue. The worker
1521  * routine does the job of allocating the map registers at
1522  * PASSIVE_LEVEL and calling the ExecutionRoutine.
1523  */
1524 
1525  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1526 
1527  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1528  {
1529  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, NumberOfMapRegisters, 0);
1530  if (Index != MAXULONG)
1531  {
1532  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1533  if (!AdapterObject->ScatterGather)
1534  {
1535  AdapterObject->MapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1536  }
1537  }
1538  }
1539 
1540  if (Index == MAXULONG)
1541  {
1542  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1543 
1545  sizeof(GROW_WORK_ITEM),
1546  TAG_DMA);
1547  if (WorkItem)
1548  {
1550  WorkItem->AdapterObject = AdapterObject;
1551  WorkItem->NumberOfMapRegisters = NumberOfMapRegisters;
1552 
1553  ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue);
1554  }
1555 
1556  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1557 
1558  return STATUS_SUCCESS;
1559  }
1560 
1561  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1562  }
1563  else
1564  {
1565  AdapterObject->MapRegisterBase = NULL;
1566  AdapterObject->NumberOfMapRegisters = 0;
1567  }
1568 
1569  AdapterObject->CurrentWcb = WaitContextBlock;
1570 
1571  Result = ExecutionRoutine(WaitContextBlock->DeviceObject,
1572  WaitContextBlock->CurrentIrp,
1573  AdapterObject->MapRegisterBase,
1574  WaitContextBlock->DeviceContext);
1575 
1576  /*
1577  * Possible return values:
1578  *
1579  * - KeepObject
1580  * Don't free any resources, the ADAPTER_OBJECT is still in use and
1581  * the caller will call IoFreeAdapterChannel later.
1582  *
1583  * - DeallocateObject
1584  * Deallocate the map registers and release the ADAPTER_OBJECT, so
1585  * someone else can use it.
1586  *
1587  * - DeallocateObjectKeepRegisters
1588  * Release the ADAPTER_OBJECT, but hang on to the map registers. The
1589  * client will later call IoFreeMapRegisters.
1590  *
1591  * NOTE:
1592  * IoFreeAdapterChannel runs the queue, so it must be called unless
1593  * the adapter object is not to be freed.
1594  */
1595  if (Result == DeallocateObject)
1596  {
1597  IoFreeAdapterChannel(AdapterObject);
1598  }
1600  {
1601  AdapterObject->NumberOfMapRegisters = 0;
1602  IoFreeAdapterChannel(AdapterObject);
1603  }
1604 
1605  return STATUS_SUCCESS;
1606 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
#define InsertTailList(ListHead, Entry)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint32_t ULONG_PTR
Definition: typedefs.h:65
UCHAR KIRQL
Definition: env_spec_w32.h:591
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
_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)
VOID NTAPI IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:103
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
#define ASSERT(a)
Definition: mode.c:44
_In_ WDFCOLLECTION _In_ ULONG Index
VOID NTAPI HalpGrowMapBufferWorker(IN PVOID DeferredContext)
Definition: dma.c:1406
BOOLEAN NTAPI KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
Definition: devqueue.c:41
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define TAG_DMA
Definition: dma.c:160
#define MAXULONG
Definition: typedefs.h:251
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define MAP_BASE_SW_SG
Definition: haldma.h:367
#define NULL
Definition: types.h:112
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
_In_ PDEVICE_OBJECT _In_ ULONG _In_ PDRIVER_CONTROL ExecutionRoutine
Definition: iofuncs.h:1397
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:110

◆ HalAllocateCommonBuffer()

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

Definition at line 913 of file dma.c.

917 {
920  PHYSICAL_ADDRESS BoundryAddressMultiple;
922 
925  BoundryAddressMultiple.QuadPart = 0;
926 
927  /*
928  * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For
929  * slave DMA devices the 64Kb boundary mustn't be crossed since the
930  * controller wouldn't be able to handle it.
931  */
932  if (AdapterObject->MasterDevice)
933  {
934  BoundryAddressMultiple.HighPart = 1;
935  }
936  else
937  {
938  BoundryAddressMultiple.LowPart = 0x10000;
939  }
940 
944  BoundryAddressMultiple,
945  CacheEnabled ? MmCached :
946  MmNonCached);
947  if (VirtualAddress == NULL) return NULL;
948 
949  *LogicalAddress = MmGetPhysicalAddress(VirtualAddress);
950 
951  return VirtualAddress;
952 }
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:235
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
_Out_ PNDIS_HANDLE _Out_ PUINT _In_ PNDIS_STRING _In_ NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
Definition: ndis.h:3227
ULONG LowPart
Definition: typedefs.h:106
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS LowestAcceptableAddress
Definition: mmfuncs.h:214
#define NULL
Definition: types.h:112
PHYSICAL_ADDRESS NTAPI MmGetPhysicalAddress(IN PVOID Address)
Definition: stubs.c:685
LONGLONG QuadPart
Definition: typedefs.h:114
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 2325 of file dma.c.

2327 {
2328  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
2329  ULONG MapRegisterNumber;
2330 
2331  /* Check if it needs map registers */
2332  if (AdapterObject->NeedsMapRegisters)
2333  {
2334  /* Check if we have enough */
2335  if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
2336  {
2337  /* We don't, fail */
2338  AdapterObject->NumberOfMapRegisters = 0;
2339  return NULL;
2340  }
2341 
2342  /* Try to find free map registers */
2343  MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
2345  0);
2346 
2347  /* Check if nothing was found */
2348  if (MapRegisterNumber == MAXULONG)
2349  {
2350  /* No free registers found, so use the base registers */
2351  RtlSetBits(MasterAdapter->MapRegisters,
2352  0,
2354  MapRegisterNumber = 0;
2355  }
2356 
2357  /* Calculate the new base */
2358  AdapterObject->MapRegisterBase =
2359  (PROS_MAP_REGISTER_ENTRY)(MasterAdapter->MapRegisterBase +
2360  MapRegisterNumber);
2361 
2362  /* Check if scatter gather isn't supported */
2363  if (!AdapterObject->ScatterGather)
2364  {
2365  /* Set the flag */
2366  AdapterObject->MapRegisterBase =
2368  ((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
2369  }
2370  }
2371  else
2372  {
2373  AdapterObject->MapRegisterBase = NULL;
2374  AdapterObject->NumberOfMapRegisters = 0;
2375  }
2376 
2377  /* Return the base */
2378  return AdapterObject->MapRegisterBase;
2379 }
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
uint32_t ULONG_PTR
Definition: typedefs.h:65
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
#define MAXULONG
Definition: typedefs.h:251
#define MAP_BASE_SW_SG
Definition: haldma.h:367
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1

◆ HalBuildMdlFromScatterGatherList()

NTSTATUS NTAPI HalBuildMdlFromScatterGatherList ( IN PDMA_ADAPTER  DmaAdapter,
IN PSCATTER_GATHER_LIST  ScatterGather,
IN PMDL  OriginalMdl,
OUT PMDL TargetMdl 
)

Definition at line 1299 of file dma.c.

1304 {
1305  UNIMPLEMENTED;
1306  return STATUS_NOT_IMPLEMENTED;
1307 }
return STATUS_NOT_IMPLEMENTED
#define UNIMPLEMENTED
Definition: debug.h:115

◆ HalBuildScatterGatherList()

NTSTATUS NTAPI HalBuildScatterGatherList ( IN PADAPTER_OBJECT  AdapterObject,
IN PDEVICE_OBJECT  DeviceObject,
IN PMDL  Mdl,
IN PVOID  CurrentVa,
IN ULONG  Length,
IN PDRIVER_LIST_CONTROL  ExecutionRoutine,
IN PVOID  Context,
IN BOOLEAN  WriteToDevice,
IN PVOID  ScatterGatherBuffer,
IN ULONG  ScatterGatherLength 
)

Definition at line 1219 of file dma.c.

1230 {
1231  NTSTATUS Status;
1232  ULONG SgSize, NumberOfMapRegisters;
1233  PSCATTER_GATHER_CONTEXT ScatterGatherContext;
1234  BOOLEAN UsingUserBuffer;
1235 
1236  Status = HalCalculateScatterGatherListSize(AdapterObject,
1237  Mdl,
1238  CurrentVa,
1239  Length,
1240  &SgSize,
1242  if (!NT_SUCCESS(Status)) return Status;
1243 
1244  if (ScatterGatherBuffer)
1245  {
1246  /* Checking if user buffer is enough */
1247  if (ScatterGatherBufferLength < SgSize)
1248  {
1249  return STATUS_BUFFER_TOO_SMALL;
1250  }
1251  UsingUserBuffer = TRUE;
1252  }
1253  else
1254  {
1255  ScatterGatherBuffer = ExAllocatePoolWithTag(NonPagedPool, SgSize, TAG_DMA);
1256  if (!ScatterGatherBuffer)
1257  {
1259  }
1260  UsingUserBuffer = FALSE;
1261  }
1262 
1263  {
1264  ScatterGatherContext = (PSCATTER_GATHER_CONTEXT)ScatterGatherBuffer;
1265 
1266  /* Fill the scatter-gather context */
1267  ScatterGatherContext->UsingUserBuffer = UsingUserBuffer;
1268  ScatterGatherContext->AdapterObject = AdapterObject;
1269  ScatterGatherContext->Mdl = Mdl;
1270  ScatterGatherContext->CurrentVa = CurrentVa;
1271  ScatterGatherContext->Length = Length;
1272  ScatterGatherContext->MapRegisterCount = NumberOfMapRegisters;
1273  ScatterGatherContext->AdapterListControlRoutine = ExecutionRoutine;
1274  ScatterGatherContext->AdapterListControlContext = Context;
1275  ScatterGatherContext->WriteToDevice = WriteToDevice;
1276 
1277  ScatterGatherContext->Wcb.DeviceObject = DeviceObject;
1278  ScatterGatherContext->Wcb.DeviceContext = (PVOID)ScatterGatherContext;
1279  ScatterGatherContext->Wcb.CurrentIrp = DeviceObject->CurrentIrp;
1280 
1281  Status = HalAllocateAdapterChannel(AdapterObject,
1282  &ScatterGatherContext->Wcb,
1285 
1286  if (!NT_SUCCESS(Status))
1287  {
1288  if (!UsingUserBuffer)
1289  ExFreePoolWithTag(ScatterGatherBuffer, TAG_DMA);
1290  return Status;
1291  }
1292  }
1293 
1294  return STATUS_SUCCESS;
1295 }
PDRIVER_LIST_CONTROL AdapterListControlRoutine
Definition: dma.c:982
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
ULONG MapRegisterCount
Definition: dma.c:984
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define FALSE
Definition: types.h:117
NTSTATUS NTAPI HalAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, IN PWAIT_CONTEXT_BLOCK WaitContextBlock, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine)
Definition: dma.c:88
unsigned char BOOLEAN
void * PVOID
Definition: retypes.h:9
Status
Definition: gdiplustypes.h:24
PADAPTER_OBJECT AdapterObject
Definition: dma.c:978
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOLEAN UsingUserBuffer
Definition: dma.c:977
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TAG_DMA
Definition: dma.c:160
WAIT_CONTEXT_BLOCK Wcb
Definition: dma.c:986
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:989
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
struct tagContext Context
Definition: acpixf.h:1034
_In_ PDEVICE_OBJECT _In_ ULONG _In_ PDRIVER_CONTROL ExecutionRoutine
Definition: iofuncs.h:1397
PVOID AdapterListControlContext
Definition: dma.c:983
unsigned int ULONG
Definition: retypes.h:1
IO_ALLOCATION_ACTION NTAPI HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context)
Definition: dma.c:992
#define STATUS_SUCCESS
Definition: shellext.h:65
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
struct _SCATTER_GATHER_CONTEXT * PSCATTER_GATHER_CONTEXT
BOOLEAN WriteToDevice
Definition: dma.c:985
NTSTATUS NTAPI HalCalculateScatterGatherListSize(IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl OPTIONAL, IN PVOID CurrentVa, IN ULONG Length, OUT PULONG ScatterGatherListSize, OUT PULONG pNumberOfMapRegisters)
Definition: dma.c:1161

Referenced by HalGetScatterGatherList().

◆ HalCalculateScatterGatherListSize()

NTSTATUS NTAPI HalCalculateScatterGatherListSize ( IN PADAPTER_OBJECT  AdapterObject,
IN PMDL Mdl  OPTIONAL,
IN PVOID  CurrentVa,
IN ULONG  Length,
OUT PULONG  ScatterGatherListSize,
OUT PULONG  pNumberOfMapRegisters 
)

Definition at line 1161 of file dma.c.

1168 {
1170  ULONG SgSize;
1171 
1173 
1175  SgSize = sizeof(SCATTER_GATHER_CONTEXT);
1176 
1177  *ScatterGatherListSize = SgSize;
1178  if (pNumberOfMapRegisters) *pNumberOfMapRegisters = NumberOfMapRegisters;
1179 
1180  return STATUS_SUCCESS;
1181 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
struct _SCATTER_GATHER_CONTEXT SCATTER_GATHER_CONTEXT
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65
#define UNIMPLEMENTED_ONCE
Definition: typedefs.h:30

Referenced by HalBuildScatterGatherList().

◆ HalFlushCommonBuffer()

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

Definition at line 2311 of file dma.c.

2315 {
2316  /* Function always returns true */
2317  return TRUE;
2318 }
#define TRUE
Definition: types.h:120

◆ HalFreeCommonBuffer()

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

Definition at line 965 of file dma.c.

970 {
972  Length,
973  CacheEnabled ? MmCached : MmNonCached);
974 }
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
VOID NTAPI MmFreeContiguousMemorySpecifyCache(IN PVOID BaseAddress, IN SIZE_T NumberOfBytes, IN MEMORY_CACHING_TYPE CacheType)
Definition: contmem.c:666

◆ HalGetAdapter()

PADAPTER_OBJECT NTAPI HalGetAdapter ( IN PDEVICE_DESCRIPTION  DeviceDescription,
OUT PULONG  NumberOfMapRegisters 
)

Definition at line 665 of file dma.c.

667 {
668  PADAPTER_OBJECT AdapterObject = NULL;
670  ULONG MapRegisters;
672  KIRQL OldIrql;
673 
674  /* Validate parameters in device description */
675  if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION2) return NULL;
676 
677  /*
678  * See if we're going to use ISA/EISA DMA adapter. These adapters are
679  * special since they're reused.
680  *
681  * Also note that we check for channel number since there are only 8 DMA
682  * channels on ISA, so any request above this requires new adapter.
683  */
684  if (((DeviceDescription->InterfaceType == Eisa) ||
685  (DeviceDescription->InterfaceType == Isa)) || !(DeviceDescription->Master))
686  {
687  if (((DeviceDescription->InterfaceType == Isa) ||
688  (DeviceDescription->InterfaceType == Eisa)) &&
689  (DeviceDescription->DmaChannel >= 8))
690  {
691  EisaAdapter = FALSE;
692  }
693  else
694  {
695  EisaAdapter = TRUE;
696  }
697  }
698  else
699  {
700  EisaAdapter = FALSE;
701  }
702 
703  /*
704  * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used
705  * for cascading the controllers and it's not available for software use.
706  */
707  if ((EisaAdapter) && (DeviceDescription->DmaChannel == 4)) return NULL;
708 
709  /*
710  * Calculate the number of map registers.
711  *
712  * - For EISA and PCI scatter/gather no map registers are needed.
713  * - For ISA slave scatter/gather one map register is needed.
714  * - For all other cases the number of map registers depends on
715  * DeviceDescription->MaximumLength.
716  */
717  MaximumLength = DeviceDescription->MaximumLength & MAXLONG;
718  if ((DeviceDescription->ScatterGather) &&
719  ((DeviceDescription->InterfaceType == Eisa) ||
720  (DeviceDescription->InterfaceType == PCIBus)))
721  {
722  MapRegisters = 0;
723  }
724  else if ((DeviceDescription->ScatterGather) && !(DeviceDescription->Master))
725  {
726  MapRegisters = 1;
727  }
728  else
729  {
730  /*
731  * In the equation below the additional map register added by
732  * the "+1" accounts for the case when a transfer does not start
733  * at a page-aligned address.
734  */
735  MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1;
736  if (MapRegisters > 16) MapRegisters = 16;
737  }
738 
739  /*
740  * Acquire the DMA lock that is used to protect the EISA adapter array.
741  */
743 
744  /*
745  * Now we must get ahold of the adapter object. For first eight ISA/EISA
746  * channels there are static adapter objects that are reused and updated
747  * on succesive HalGetAdapter calls. In other cases a new adapter object
748  * is always created and it's to the DMA adapter list (HalpDmaAdapterList).
749  */
750  if (EisaAdapter)
751  {
752  AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel];
753  if (AdapterObject)
754  {
755  if ((AdapterObject->NeedsMapRegisters) &&
756  (MapRegisters > AdapterObject->MapRegistersPerChannel))
757  {
758  AdapterObject->MapRegistersPerChannel = MapRegisters;
759  }
760  }
761  }
762 
763  if (AdapterObject == NULL)
764  {
765  AdapterObject = HalpDmaAllocateChildAdapter(MapRegisters, DeviceDescription);
766  if (AdapterObject == NULL)
767  {
768  KeSetEvent(&HalpDmaLock, 0, 0);
769  return NULL;
770  }
771 
772  if (EisaAdapter)
773  {
774  HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject;
775  }
776 
777  if (MapRegisters > 0)
778  {
779  AdapterObject->NeedsMapRegisters = TRUE;
780  AdapterObject->MapRegistersPerChannel = MapRegisters;
781  }
782  else
783  {
784  AdapterObject->NeedsMapRegisters = FALSE;
785  if (DeviceDescription->Master)
786  {
787  AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1;
788  }
789  else
790  {
791  AdapterObject->MapRegistersPerChannel = 1;
792  }
793  }
794  }
795 
796  /*
797  * Release the DMA lock. HalpEisaAdapter will no longer be touched,
798  * so we don't need it.
799  */
800  KeSetEvent(&HalpDmaLock, 0, 0);
801 
802  if (!EisaAdapter)
803  {
804  /* If it's not one of the static adapters, add it to the list */
806  InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList);
808  }
809 
810  /*
811  * Setup the values in the adapter object that are common for all
812  * types of buses.
813  */
815  {
816  AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount;
817  }
818  else
819  {
820  AdapterObject->IgnoreCount = 0;
821  }
822 
823  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
824  AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses;
825  AdapterObject->ScatterGather = DeviceDescription->ScatterGather;
826  AdapterObject->MasterDevice = DeviceDescription->Master;
827  *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel;
828 
829  /*
830  * For non-(E)ISA adapters we have already done all the work. On the
831  * other hand for (E)ISA adapters we must still setup the DMA modes
832  * and prepare the controller.
833  */
834  if (EisaAdapter)
835  {
836  if (!HalpDmaInitializeEisaAdapter(AdapterObject, DeviceDescription))
837  {
838  ObDereferenceObject(AdapterObject);
839  return NULL;
840  }
841  }
842 
843  return AdapterObject;
844 }
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
#define MAXLONG
Definition: umtypes.h:116
static PADAPTER_OBJECT HalpEisaAdapter[8]
Definition: dma.c:86
#define TRUE
Definition: types.h:120
BOOLEAN NTAPI HalpDmaInitializeEisaAdapter(IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:518
PADAPTER_OBJECT NTAPI HalpDmaAllocateChildAdapter(IN ULONG NumberOfMapRegisters, IN PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:455
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
#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 KEVENT HalpDmaLock
Definition: dma.c:83
UCHAR KIRQL
Definition: env_spec_w32.h:591
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ PCUNICODE_STRING DeviceDescription
Definition: wdfpdo.h:430
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
static KSPIN_LOCK HalpDmaAdapterListLock
Definition: dma.c:84
_In_ WDFDMATRANSACTION _In_ size_t MaximumLength
#define ObDereferenceObject
Definition: obfuncs.h:203
#define BYTES_TO_PAGES(Size)
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
static LIST_ENTRY HalpDmaAdapterList
Definition: dma.c:85
#define NULL
Definition: types.h:112
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define DEVICE_DESCRIPTION_VERSION2
Definition: iotypes.h:2065
unsigned int ULONG
Definition: retypes.h:1
#define DEVICE_DESCRIPTION_VERSION1
Definition: iotypes.h:2064

◆ HalGetScatterGatherList()

NTSTATUS NTAPI HalGetScatterGatherList ( IN PADAPTER_OBJECT  AdapterObject,
IN PDEVICE_OBJECT  DeviceObject,
IN PMDL  Mdl,
IN PVOID  CurrentVa,
IN ULONG  Length,
IN PDRIVER_LIST_CONTROL  ExecutionRoutine,
IN PVOID  Context,
IN BOOLEAN  WriteToDevice 
)

Definition at line 1086 of file dma.c.

1094 {
1095  return HalBuildScatterGatherList(AdapterObject,
1096  DeviceObject,
1097  Mdl,
1098  CurrentVa,
1099  Length,
1101  Context,
1102  WriteToDevice,
1103  NULL,
1104  0);
1105 }
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:989
#define NULL
Definition: types.h:112
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_In_ PDEVICE_OBJECT _In_ ULONG _In_ PDRIVER_CONTROL ExecutionRoutine
Definition: iofuncs.h:1397
NTSTATUS NTAPI HalBuildScatterGatherList(IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_OBJECT DeviceObject, IN PMDL Mdl, IN PVOID CurrentVa, IN ULONG Length, IN PDRIVER_LIST_CONTROL ExecutionRoutine, IN PVOID Context, IN BOOLEAN WriteToDevice, IN PVOID ScatterGatherBuffer, IN ULONG ScatterGatherLength)
Definition: dma.c:1219

◆ HalpCopyBufferMap()

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

Definition at line 1837 of file dma.c.

1842 {
1843  ULONG CurrentLength;
1844  ULONG_PTR CurrentAddress;
1845  ULONG ByteOffset;
1847 
1849  if (!VirtualAddress)
1850  {
1851  /*
1852  * NOTE: On real NT a mechanism with reserved pages is implemented
1853  * to handle this case in a slow, but graceful non-fatal way.
1854  */
1855  KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0);
1856  }
1857 
1858  CurrentAddress = (ULONG_PTR)VirtualAddress +
1859  (ULONG_PTR)CurrentVa -
1861 
1862  while (Length > 0)
1863  {
1864  ByteOffset = BYTE_OFFSET(CurrentAddress);
1865  CurrentLength = PAGE_SIZE - ByteOffset;
1866  if (CurrentLength > Length) CurrentLength = Length;
1867 
1868  if (WriteToDevice)
1869  {
1870  RtlCopyMemory((PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1871  (PVOID)CurrentAddress,
1872  CurrentLength);
1873  }
1874  else
1875  {
1876  RtlCopyMemory((PVOID)CurrentAddress,
1877  (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1878  CurrentLength);
1879  }
1880 
1881  Length -= CurrentLength;
1882  CurrentAddress += CurrentLength;
1883  MapRegisterBase++;
1884  }
1885 }
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define MmGetMdlVirtualAddress(_Mdl)
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
uint32_t ULONG_PTR
Definition: typedefs.h:65
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:989
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:212
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#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:108
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:725

Referenced by IoFlushAdapterBuffers(), and IoMapTransfer().

◆ HalpDmaAllocateChildAdapter()

PADAPTER_OBJECT NTAPI HalpDmaAllocateChildAdapter ( IN ULONG  NumberOfMapRegisters,
IN PDEVICE_DESCRIPTION  DeviceDescription 
)

Definition at line 455 of file dma.c.

457 {
458  PADAPTER_OBJECT AdapterObject;
461  HANDLE Handle;
462 
464  NULL,
466  NULL,
467  NULL);
468 
472  KernelMode,
473  NULL,
474  sizeof(ADAPTER_OBJECT),
475  0,
476  0,
477  (PVOID)&AdapterObject);
478  if (!NT_SUCCESS(Status)) return NULL;
479 
480  Status = ObReferenceObjectByPointer(AdapterObject,
483  KernelMode);
484  if (!NT_SUCCESS(Status)) return NULL;
485 
486  RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
487 
488  Status = ObInsertObject(AdapterObject,
489  NULL,
491  0,
492  NULL,
493  &Handle);
494  if (!NT_SUCCESS(Status)) return NULL;
495 
496  ZwClose(Handle);
497 
498  AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version;
499  AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT);
500  AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations;
501  AdapterObject->MapRegistersPerChannel = 1;
502  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
503  AdapterObject->ChannelNumber = 0xFF;
504  AdapterObject->MasterAdapter = HalpMasterAdapter;
505  KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
506 
507  return AdapterObject;
508 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:22
USHORT Size
Definition: iotypes.h:2294
static DMA_OPERATIONS HalpDmaOperations
Definition: dma.c:138
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
struct _DMA_OPERATIONS * DmaOperations
Definition: iotypes.h:2295
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ PCUNICODE_STRING DeviceDescription
Definition: wdfpdo.h:430
#define FILE_READ_DATA
Definition: nt_native.h:628
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:381
#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
Status
Definition: gdiplustypes.h:24
USHORT Version
Definition: iotypes.h:2293
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
POBJECT_TYPE IoAdapterObjectType
Definition: adapter.c:18
#define OBJ_PERMANENT
Definition: winternl.h:226
static PADAPTER_OBJECT HalpMasterAdapter
Definition: dma.c:90
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:2931
unsigned short USHORT
Definition: pedump.c:61
#define NULL
Definition: types.h:112
_In_ HANDLE Handle
Definition: extypes.h:390
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106

Referenced by HalGetAdapter().

◆ HalpDmaAllocateMasterAdapter()

PADAPTER_OBJECT NTAPI HalpDmaAllocateMasterAdapter ( VOID  )

Definition at line 398 of file dma.c.

399 {
400  PADAPTER_OBJECT MasterAdapter;
401  ULONG Size, SizeOfBitmap;
402 
403  SizeOfBitmap = MAX_MAP_REGISTERS;
404  Size = sizeof(ADAPTER_OBJECT);
405  Size += sizeof(RTL_BITMAP);
406  Size += (SizeOfBitmap + 7) >> 3;
407 
408  MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA);
409  if (!MasterAdapter) return NULL;
410 
411  RtlZeroMemory(MasterAdapter, Size);
412 
413  KeInitializeSpinLock(&MasterAdapter->SpinLock);
414  InitializeListHead(&MasterAdapter->AdapterQueue);
415 
416  MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1);
417  RtlInitializeBitMap(MasterAdapter->MapRegisters,
418  (PULONG)(MasterAdapter->MapRegisters + 1),
419  SizeOfBitmap);
420  RtlSetAllBits(MasterAdapter->MapRegisters);
421  MasterAdapter->NumberOfMapRegisters = 0;
422  MasterAdapter->CommittedMapRegisters = 0;
423 
424  MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(NonPagedPool,
425  SizeOfBitmap *
426  sizeof(ROS_MAP_REGISTER_ENTRY),
427  TAG_DMA);
428  if (!MasterAdapter->MapRegisterBase)
429  {
430  ExFreePool(MasterAdapter);
431  return NULL;
432  }
433 
434  RtlZeroMemory(MasterAdapter->MapRegisterBase,
435  SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY));
436  if (!HalpGrowMapBuffers(MasterAdapter, 0x10000))
437  {
438  ExFreePool(MasterAdapter);
439  return NULL;
440  }
441 
442  return MasterAdapter;
443 }
struct _RTL_BITMAP RTL_BITMAP
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
Definition: haldma.h:312
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
struct _ADAPTER_OBJECT ADAPTER_OBJECT
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:238
void * PVOID
Definition: retypes.h:9
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TAG_DMA
Definition: dma.c:160
#define MAX_MAP_REGISTERS
Definition: dma.c:158
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
BOOLEAN NTAPI HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject, IN ULONG SizeOfMapBuffers)
Definition: dma.c:271
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 ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 1320 of file dma.c.

1321 {
1322  return 1;
1323 }

◆ HalpDmaInitializeEisaAdapter()

BOOLEAN NTAPI HalpDmaInitializeEisaAdapter ( IN PADAPTER_OBJECT  AdapterObject,
IN PDEVICE_DESCRIPTION  DeviceDescription 
)

Definition at line 518 of file dma.c.

520 {
521  UCHAR Controller;
522  DMA_MODE DmaMode = {{0 }};
523  DMA_EXTENDED_MODE ExtendedMode = {{ 0 }};
524  PVOID AdapterBaseVa;
525 
526  Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1;
527 
528  if (Controller == 1)
529  {
530  AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController1));
531  }
532  else
533  {
534  AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2));
535  }
536 
537  AdapterObject->AdapterNumber = Controller;
538  AdapterObject->ChannelNumber = (UCHAR)(DeviceDescription->DmaChannel & 3);
539  AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel];
540  AdapterObject->Width16Bits = FALSE;
541  AdapterObject->AdapterBaseVa = AdapterBaseVa;
542 
543  if (HalpEisaDma)
544  {
545  ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber;
546 
547  switch (DeviceDescription->DmaSpeed)
548  {
549  case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break;
550  case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break;
551  case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break;
552  case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break;
553  default:
554  return FALSE;
555  }
556 
557  switch (DeviceDescription->DmaWidth)
558  {
559  case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break;
560  case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break;
561  case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break;
562  default:
563  return FALSE;
564  }
565 
566  if (Controller == 1)
567  {
569  ExtendedMode.Byte);
570  }
571  else
572  {
574  ExtendedMode.Byte);
575  }
576  }
577  else
578  {
579  /*
580  * Validate setup for non-busmaster DMA adapter. Secondary controller
581  * supports only 16-bit transfers and main controller supports only
582  * 8-bit transfers. Anything else is invalid.
583  */
584  if (!DeviceDescription->Master)
585  {
586  if ((Controller == 2) && (DeviceDescription->DmaWidth == Width16Bits))
587  {
588  AdapterObject->Width16Bits = TRUE;
589  }
590  else if ((Controller != 1) || (DeviceDescription->DmaWidth != Width8Bits))
591  {
592  return FALSE;
593  }
594  }
595  }
596 
597  DmaMode.Channel = AdapterObject->ChannelNumber;
598  DmaMode.AutoInitialize = DeviceDescription->AutoInitialize;
599 
600  /*
601  * Set the DMA request mode.
602  *
603  * For (E)ISA bus master devices just unmask (enable) the DMA channel
604  * and set it to cascade mode. Otherwise just select the right one
605  * bases on the passed device description.
606  */
607  if (DeviceDescription->Master)
608  {
610  if (Controller == 1)
611  {
612  /* Set the Request Data */
614  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
615 
616  /* Unmask DMA Channel */
617  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask,
618  AdapterObject->ChannelNumber | DMA_CLEARMASK);
619  }
620  else
621  {
622  /* Set the Request Data */
623  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
624 
625  /* Unmask DMA Channel */
626  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask,
627  AdapterObject->ChannelNumber | DMA_CLEARMASK);
628  }
629  }
630  else
631  {
632  if (DeviceDescription->DemandMode)
633  {
635  }
636  else
637  {
639  }
640  }
641 
642  AdapterObject->AdapterMode = DmaMode;
643 
644  return TRUE;
645 }
UCHAR AutoInitialize
Definition: haldma.h:95
#define B_32BITS
Definition: haldma.h:145
_In_ ULONG Mode
Definition: hubbusif.h:303
#define TRUE
Definition: types.h:120
unsigned char * PUCHAR
Definition: retypes.h:3
#define B_16BITS
Definition: haldma.h:146
#define TypeA
Definition: nslookup.h:13
static const ULONG_PTR HalpEisaPortPage[8]
Definition: dma.c:93
UCHAR Byte
Definition: haldma.h:99
if(dx==0 &&dy==0)
Definition: linetemp.h:174
#define BURST_TIMING
Definition: haldma.h:152
#define __WARNING_DEREF_NULL_PTR
Definition: suppress.h:32
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ PCUNICODE_STRING DeviceDescription
Definition: wdfpdo.h:430
#define FALSE
Definition: types.h:117
#define TYPE_A_TIMING
Definition: haldma.h:150
UCHAR Channel
Definition: haldma.h:93
#define COMPATIBLE_TIMING
Definition: haldma.h:149
#define UlongToPtr(u)
Definition: config.h:106
#define SINGLE_REQUEST_MODE
Definition: haldma.h:170
#define CASCADE_REQUEST_MODE
Definition: haldma.h:172
unsigned char UCHAR
Definition: xmlstorage.h:181
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
UCHAR ChannelNumber
Definition: haldma.h:133
#define B_8BITS
Definition: haldma.h:143
#define TYPE_B_TIMING
Definition: haldma.h:151
UCHAR RequestMode
Definition: haldma.h:97
UCHAR TransferSize
Definition: haldma.h:134
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define DMA_CLEARMASK
Definition: haldma.h:175
static BOOLEAN HalpEisaDma
Definition: dma.c:88
#define DEMAND_REQUEST_MODE
Definition: haldma.h:169
#define _PRAGMA_WARNING_SUPPRESS(x)
Definition: suppress.h:28
UCHAR TimingMode
Definition: haldma.h:135

Referenced by HalGetAdapter().

◆ HalpGetAdapterMaximumPhysicalAddress()

PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 235 of file dma.c.

236 {
237  PHYSICAL_ADDRESS HighestAddress;
238 
239  if (AdapterObject->MasterDevice)
240  {
241  if (AdapterObject->Dma64BitAddresses)
242  {
243  HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
244  return HighestAddress;
245  }
246  else if (AdapterObject->Dma32BitAddresses)
247  {
248  HighestAddress.QuadPart = 0xFFFFFFFF;
249  return HighestAddress;
250  }
251  }
252 
253  HighestAddress.QuadPart = 0xFFFFFF;
254  return HighestAddress;
255 }
#define ULL(a, b)
Definition: format_msg.c:27
LONGLONG QuadPart
Definition: typedefs.h:114

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 856 of file dma.c.

859 {
861 }
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ PCUNICODE_STRING DeviceDescription
Definition: wdfpdo.h:430
PADAPTER_OBJECT NTAPI HalGetAdapter(IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
Definition: dma.c:22

Referenced by HalpInitDma().

◆ HalpGrowMapBuffers()

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

Definition at line 271 of file dma.c.

273 {
278  PHYSICAL_ADDRESS BoundryAddressMultiple;
279  KIRQL OldIrql;
281 
282  /* Check if enough map register slots are available. */
283  MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers);
284  if (MapRegisterCount + AdapterObject->NumberOfMapRegisters > MAX_MAP_REGISTERS)
285  {
286  DPRINT("No more map register slots available! (Current: %d | Requested: %d | Limit: %d)\n",
287  AdapterObject->NumberOfMapRegisters,
290  return FALSE;
291  }
292 
293  /*
294  * Allocate memory for the new map registers. For 32-bit adapters we use
295  * two passes in order not to waste scare resource (low memory).
296  */
299  LowestAcceptableAddress.LowPart = HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0;
300  BoundryAddressMultiple.QuadPart = 0;
301 
305  BoundryAddressMultiple,
306  MmNonCached);
308  {
313  BoundryAddressMultiple,
314  MmNonCached);
315  }
316 
317  if (!VirtualAddress) return FALSE;
318 
320 
321  /*
322  * All the following must be done with the master adapter lock held
323  * to prevent corruption.
324  */
325  KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql);
326 
327  /*
328  * Setup map register entries for the buffer allocated. Each entry has
329  * a virtual and physical address and corresponds to PAGE_SIZE large
330  * buffer.
331  */
332  if (MapRegisterCount > 0)
333  {
334  PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry;
335 
336  CurrentEntry = AdapterObject->MapRegisterBase + AdapterObject->NumberOfMapRegisters;
337  do
338  {
339  /*
340  * Leave one entry free for every non-contiguous memory region
341  * in the map register bitmap. This ensures that we can search
342  * using RtlFindClearBits for contiguous map register regions.
343  *
344  * Also for non-EISA DMA leave one free entry for every 64Kb
345  * break, because the DMA controller can handle only coniguous
346  * 64Kb regions.
347  */
348  if (CurrentEntry != AdapterObject->MapRegisterBase)
349  {
350  PreviousEntry = CurrentEntry - 1;
351  if ((PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE) == PhysicalAddress.LowPart)
352  {
353  if (!HalpEisaDma)
354  {
355  if ((PreviousEntry->PhysicalAddress.LowPart ^ PhysicalAddress.LowPart) & 0xFFFF0000)
356  {
357  CurrentEntry++;
358  AdapterObject->NumberOfMapRegisters++;
359  }
360  }
361  }
362  else
363  {
364  CurrentEntry++;
365  AdapterObject->NumberOfMapRegisters++;
366  }
367  }
368 
369  RtlClearBit(AdapterObject->MapRegisters,
370  (ULONG)(CurrentEntry - AdapterObject->MapRegisterBase));
371  CurrentEntry->VirtualAddress = VirtualAddress;
372  CurrentEntry->PhysicalAddress = PhysicalAddress;
373 
376 
377  CurrentEntry++;
378  AdapterObject->NumberOfMapRegisters++;
380  } while (MapRegisterCount);
381  }
382 
383  KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
384 
385  return TRUE;
386 }
#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
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:235
_In_ WDFDMATRANSACTION _Out_opt_ ULONG * MapRegisterCount
uint32_t ULONG_PTR
Definition: typedefs.h:65
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
void * PVOID
Definition: retypes.h:9
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:1098
_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:106
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS LowestAcceptableAddress
Definition: mmfuncs.h:214
#define MAX_MAP_REGISTERS
Definition: dma.c:158
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
unsigned int ULONG
Definition: retypes.h:1
PHYSICAL_ADDRESS NTAPI MmGetPhysicalAddress(IN PVOID Address)
Definition: stubs.c:685
#define DPRINT
Definition: sndvol32.h:71
static BOOLEAN HalpEisaDma
Definition: dma.c:88
LONGLONG QuadPart
Definition: typedefs.h:114
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 HalpDmaAllocateMasterAdapter(), and HalpGrowMapBufferWorker().

◆ HalpGrowMapBufferWorker()

VOID NTAPI HalpGrowMapBufferWorker ( IN PVOID  DeferredContext)

Definition at line 1406 of file dma.c.

1407 {
1409  KIRQL OldIrql;
1410  BOOLEAN Succeeded;
1411 
1412  /*
1413  * Try to allocate new map registers for the adapter.
1414  *
1415  * NOTE: The NT implementation actually tries to allocate more map
1416  * registers than needed as an optimization.
1417  */
1419  Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter,
1420  WorkItem->NumberOfMapRegisters << PAGE_SHIFT);
1421  KeSetEvent(&HalpDmaLock, 0, 0);
1422 
1423  if (Succeeded)
1424  {
1425  /*
1426  * Flush the adapter queue now that new map registers are ready. The
1427  * easiest way to do that is to call IoFreeMapRegisters to not free
1428  * any registers. Note that we use the magic (PVOID)2 map register
1429  * base to bypass the parameter checking.
1430  */
1432  IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
1434  }
1435 
1437 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
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
static KEVENT HalpDmaLock
Definition: dma.c:83
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
_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
VOID FASTCALL KfLowerIrql(IN KIRQL NewIrql)
Definition: pic.c:232
#define NULL
Definition: types.h:112
BOOLEAN NTAPI HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject, IN ULONG SizeOfMapBuffers)
Definition: dma.c:271
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:110
struct _GROW_WORK_ITEM * PGROW_WORK_ITEM
#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 185 of file dma.c.

186 {
187  /*
188  * Initialize the DMA Operation table
189  */
195 
197  {
198  /*
199  * Check if Extended DMA is available. We're just going to do a random
200  * read and write.
201  */
202  WRITE_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)), 0x2A);
203  if (READ_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2))) == 0x2A)
204  {
205  DPRINT1("Machine supports EISA DMA. Bus type: %lu\n", HalpBusType);
206  HalpEisaDma = TRUE;
207  }
208  }
209 
210  /*
211  * Intialize all the global variables and allocate master adapter with
212  * first map buffers.
213  */
218 
219  /*
220  * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's
221  * used by IoGetDmaAdapter in the kernel.
222  */
224 }
#define HalGetDmaAdapter
Definition: haltypes.h:291
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
PADAPTER_OBJECT NTAPI HalpDmaAllocateMasterAdapter(VOID)
Definition: dma.c:398
#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:2640
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:2334
PDMA_ADAPTER NTAPI HalpGetDmaAdapter(IN PVOID Context, IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
Definition: dma.c:856
static DMA_OPERATIONS HalpDmaOperations
Definition: dma.c:138
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:2343
static KEVENT HalpDmaLock
Definition: dma.c:83
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:2326
ULONG HalpBusType
Definition: pcibus.c:18
PMAP_TRANSFER MapTransfer
Definition: iotypes.h:2641
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:238
static KSPIN_LOCK HalpDmaAdapterListLock
Definition: dma.c:84
#define UlongToPtr(u)
Definition: config.h:106
VOID NTAPI IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:103
PFLUSH_ADAPTER_BUFFERS FlushAdapterBuffers
Definition: iotypes.h:2638
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:2353
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:2639
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 WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
static PADAPTER_OBJECT HalpMasterAdapter
Definition: dma.c:90
static LIST_ENTRY HalpDmaAdapterList
Definition: dma.c:85
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
PALLOCATE_ADAPTER_CHANNEL AllocateAdapterChannel
Definition: iotypes.h:2637
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
VOID(NTAPI * PFREE_MAP_REGISTERS)(_In_ PDMA_ADAPTER DmaAdapter, PVOID MapRegisterBase, ULONG NumberOfMapRegisters)
Definition: iotypes.h:2347
#define DPRINT1
Definition: precomp.h:8
static BOOLEAN HalpEisaDma
Definition: dma.c:88
#define MACHINE_TYPE_EISA
Definition: ketypes.h:53

Referenced by HalpInitPhase1().

◆ HalpScatterGatherAdapterControl()

IO_ALLOCATION_ACTION NTAPI HalpScatterGatherAdapterControl ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  MapRegisterBase,
IN PVOID  Context 
)

Definition at line 992 of file dma.c.

996 {
997  PSCATTER_GATHER_CONTEXT AdapterControlContext = Context;
998  PADAPTER_OBJECT AdapterObject = AdapterControlContext->AdapterObject;
999  PSCATTER_GATHER_LIST ScatterGatherList;
1001  ULONG ElementCount = 0, RemainingLength = AdapterControlContext->Length;
1002  PUCHAR CurrentVa = AdapterControlContext->CurrentVa;
1003 
1004  /* Store the map register base for later in HalPutScatterGatherList */
1005  AdapterControlContext->MapRegisterBase = MapRegisterBase;
1006 
1007  while (RemainingLength > 0 && ElementCount < MAX_SG_ELEMENTS)
1008  {
1009  TempElements[ElementCount].Length = RemainingLength;
1010  TempElements[ElementCount].Reserved = 0;
1011  TempElements[ElementCount].Address = IoMapTransfer(AdapterObject,
1012  AdapterControlContext->Mdl,
1014  CurrentVa + (AdapterControlContext->Length - RemainingLength),
1015  &TempElements[ElementCount].Length,
1016  AdapterControlContext->WriteToDevice);
1017  if (TempElements[ElementCount].Length == 0)
1018  break;
1019 
1020  DPRINT("Allocated one S/G element: 0x%I64u with length: 0x%x\n",
1021  TempElements[ElementCount].Address.QuadPart,
1022  TempElements[ElementCount].Length);
1023 
1024  ASSERT(TempElements[ElementCount].Length <= RemainingLength);
1025  RemainingLength -= TempElements[ElementCount].Length;
1026  ElementCount++;
1027  }
1028 
1029  if (RemainingLength > 0)
1030  {
1031  DPRINT1("Scatter/gather list construction failed!\n");
1032  return DeallocateObject;
1033  }
1034 
1035  ScatterGatherList = ExAllocatePoolWithTag(NonPagedPool,
1036  sizeof(SCATTER_GATHER_LIST) + sizeof(SCATTER_GATHER_ELEMENT) * ElementCount,
1037  TAG_DMA);
1038  ASSERT(ScatterGatherList);
1039 
1040  ScatterGatherList->NumberOfElements = ElementCount;
1041  ScatterGatherList->Reserved = (ULONG_PTR)AdapterControlContext;
1042  RtlCopyMemory(ScatterGatherList->Elements,
1043  TempElements,
1044  sizeof(SCATTER_GATHER_ELEMENT) * ElementCount);
1045 
1046  DPRINT("Initiating S/G DMA with %d element(s)\n", ElementCount);
1047 
1048  AdapterControlContext->AdapterListControlRoutine(DeviceObject,
1049  Irp,
1050  ScatterGatherList,
1051  AdapterControlContext->AdapterListControlContext);
1052 
1054 }
PDRIVER_LIST_CONTROL AdapterListControlRoutine
Definition: dma.c:982
#define MAX_SG_ELEMENTS
Definition: dma.c:80
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
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
unsigned char * PUCHAR
Definition: retypes.h:3
PHYSICAL_ADDRESS Address
Definition: iotypes.h:2173
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ PIRP Irp
Definition: csq.h:116
static WCHAR Address[46]
Definition: ping.c:68
struct _SCATTER_GATHER_LIST SCATTER_GATHER_LIST
Definition: iotypes.h:2204
PADAPTER_OBJECT AdapterObject
Definition: dma.c:978
#define ASSERT(a)
Definition: mode.c:44
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TAG_DMA
Definition: dma.c:160
PVOID MapRegisterBase
Definition: dma.c:983
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:212
#define DPRINT1
Definition: precomp.h:8
struct tagContext Context
Definition: acpixf.h:1034
PVOID AdapterListControlContext
Definition: dma.c:983
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2204
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define DPRINT
Definition: sndvol32.h:71
BOOLEAN WriteToDevice
Definition: dma.c:985

Referenced by HalBuildScatterGatherList().

◆ HalPutDmaAdapter()

VOID NTAPI HalPutDmaAdapter ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 873 of file dma.c.

874 {
875  KIRQL OldIrql;
876  if (AdapterObject->ChannelNumber == 0xFF)
877  {
879  RemoveEntryList(&AdapterObject->AdapterList);
881  }
882 
883  ObDereferenceObject(AdapterObject);
884 }
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
UCHAR KIRQL
Definition: env_spec_w32.h:591
static KSPIN_LOCK HalpDmaAdapterListLock
Definition: dma.c:84
#define ObDereferenceObject
Definition: obfuncs.h:203
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627

◆ HalPutScatterGatherList()

VOID NTAPI HalPutScatterGatherList ( IN PADAPTER_OBJECT  AdapterObject,
IN PSCATTER_GATHER_LIST  ScatterGather,
IN BOOLEAN  WriteToDevice 
)

Definition at line 1127 of file dma.c.

1130 {
1131  PSCATTER_GATHER_CONTEXT AdapterControlContext = (PSCATTER_GATHER_CONTEXT)ScatterGather->Reserved;
1132  ULONG i;
1133 
1134  for (i = 0; i < ScatterGather->NumberOfElements; i++)
1135  {
1136  IoFlushAdapterBuffers(AdapterObject,
1137  AdapterControlContext->Mdl,
1138  AdapterControlContext->MapRegisterBase,
1139  AdapterControlContext->CurrentVa,
1140  ScatterGather->Elements[i].Length,
1141  AdapterControlContext->WriteToDevice);
1142  AdapterControlContext->CurrentVa += ScatterGather->Elements[i].Length;
1143  }
1144 
1145  IoFreeMapRegisters(AdapterObject,
1146  AdapterControlContext->MapRegisterBase,
1147  AdapterControlContext->MapRegisterCount);
1148 
1149 
1151 
1152  /* If this is our buffer, release it */
1153  if (!AdapterControlContext->UsingUserBuffer)
1154  ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
1155 
1156  DPRINT("S/G DMA has finished!\n");
1157 }
ULONG MapRegisterCount
Definition: dma.c:984
VOID NTAPI IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject, IN PVOID MapRegisterBase, IN ULONG NumberOfMapRegisters)
Definition: dma.c:114
#define for
Definition: utility.h:88
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
BOOLEAN UsingUserBuffer
Definition: dma.c:977
#define TAG_DMA
Definition: dma.c:160
PVOID MapRegisterBase
Definition: dma.c:983
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_In_ struct _IRP _In_ struct _SCATTER_GATHER_LIST * ScatterGather
Definition: iotypes.h:2375
unsigned int ULONG
Definition: retypes.h:1
#define DPRINT
Definition: sndvol32.h:71
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
struct _SCATTER_GATHER_CONTEXT * PSCATTER_GATHER_CONTEXT
BOOLEAN WriteToDevice
Definition: dma.c:985

◆ HalReadDmaCounter()

ULONG NTAPI HalReadDmaCounter ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 1334 of file dma.c.

1335 {
1336  KIRQL OldIrql;
1337  ULONG Count, OldCount;
1338 
1339  ASSERT(!AdapterObject->MasterDevice);
1340 
1341  /*
1342  * Acquire the master adapter lock since we're going to mess with the
1343  * system DMA controller registers and we really don't want anyone
1344  * to do the same at the same time.
1345  */
1346  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
1347 
1348  /* Send the request to the specific controller. */
1349  if (AdapterObject->AdapterNumber == 1)
1350  {
1351  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1352 
1353  Count = 0xffff00;
1354  do
1355  {
1356  OldCount = Count;
1357 
1358  /* Send Reset */
1359  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
1360 
1361  /* Read Count */
1362  Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1363  [AdapterObject->ChannelNumber].DmaBaseCount);
1364  Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1365  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1366  } while (0xffff00 & (OldCount ^ Count));
1367  }
1368  else
1369  {
1370  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1371 
1372  Count = 0xffff00;
1373  do
1374  {
1375  OldCount = Count;
1376 
1377  /* Send Reset */
1378  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
1379 
1380  /* Read Count */
1381  Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1382  [AdapterObject->ChannelNumber].DmaBaseCount);
1383  Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1384  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1385  } while (0xffff00 & (OldCount ^ Count));
1386  }
1387 
1388  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
1389 
1390  Count++;
1391  Count &= 0xffff;
1392  if (AdapterObject->Width16Bits) Count *= 2;
1393 
1394  return Count;
1395 }
UCHAR DmaBaseCount
Definition: haldma.h:184
DMA1_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:197
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
UCHAR KIRQL
Definition: env_spec_w32.h:591
UCHAR ClearBytePointer
Definition: haldma.h:219
int Count
Definition: noreturn.cpp:7
#define ASSERT(a)
Definition: mode.c:44
DMA2_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:210
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
UCHAR DmaBaseCount
Definition: haldma.h:191
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
unsigned int ULONG
Definition: retypes.h:1
UCHAR ClearBytePointer
Definition: haldma.h:202

◆ IoFlushAdapterBuffers()

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

Definition at line 1920 of file dma.c.

1926 {
1927  BOOLEAN SlaveDma = FALSE;
1928  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1931  PPFN_NUMBER MdlPagesPtr;
1932 
1933  /* Sanity checks */
1935  ASSERT(AdapterObject);
1936 
1937  if (!AdapterObject->MasterDevice)
1938  {
1939  /* Mask out (disable) the DMA channel. */
1940  if (AdapterObject->AdapterNumber == 1)
1941  {
1942  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1943  WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
1944  AdapterObject->ChannelNumber | DMA_SETMASK);
1945  }
1946  else
1947  {
1948  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1949  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
1950  AdapterObject->ChannelNumber | DMA_SETMASK);
1951  }
1952  SlaveDma = TRUE;
1953  }
1954 
1955  /* This can happen if the device supports hardware scatter/gather. */
1956  if (MapRegisterBase == NULL) return TRUE;
1957 
1958  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1959 
1960  if (!WriteToDevice)
1961  {
1963  {
1964  if (RealMapRegisterBase->Counter != MAXULONG)
1965  {
1966  if ((SlaveDma) && !(AdapterObject->IgnoreCount))
1967  {
1968  Length -= HalReadDmaCounter(AdapterObject);
1969  }
1970  }
1972  RealMapRegisterBase,
1973  CurrentVa,
1974  Length,
1975  FALSE);
1976  }
1977  else
1978  {
1979  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1980  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1981 
1982  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1983  PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa);
1984 
1987  {
1989  RealMapRegisterBase,
1990  CurrentVa,
1991  Length,
1992  FALSE);
1993  }
1994  }
1995  }
1996 
1997  RealMapRegisterBase->Counter = 0;
1998 
1999  return TRUE;
2000 }
#define ASSERT_IRQL_LESS_OR_EQUAL(x)
Definition: debug.h:251
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
ULONG NTAPI HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:76
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define MmGetMdlPfnArray(_Mdl)
UCHAR SingleMask
Definition: haldma.h:215
VOID NTAPI HalpCopyBufferMap(IN PMDL Mdl, IN PROS_MAP_REGISTER_ENTRY MapRegisterBase, IN PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice)
Definition: dma.c:1837
#define TRUE
Definition: types.h:120
Definition: haldma.h:312
PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:235
uint32_t ULONG_PTR
Definition: typedefs.h:65
ULONG * PPFN_NUMBER
Definition: ke.h:9
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
UCHAR SingleMask
Definition: haldma.h:200
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
#define ASSERT(a)
Definition: mode.c:44
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1098
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
_Out_ PNDIS_HANDLE _Out_ PUINT _In_ PNDIS_STRING _In_ NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
Definition: ndis.h:3227
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:989
#define MAXULONG
Definition: typedefs.h:251
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:212
#define MAP_BASE_SW_SG
Definition: haldma.h:367
#define NULL
Definition: types.h:112
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
#define ULONG_PTR
Definition: config.h:101
#define DMA_SETMASK
Definition: haldma.h:174
#define BYTE_OFFSET(Va)
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG Counter
Definition: haldma.h:316

◆ IoFreeAdapterChannel()

VOID NTAPI IoFreeAdapterChannel ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 1628 of file dma.c.

1629 {
1630  PADAPTER_OBJECT MasterAdapter;
1632  PWAIT_CONTEXT_BLOCK WaitContextBlock;
1633  ULONG Index = MAXULONG;
1634  ULONG Result;
1635  KIRQL OldIrql;
1636 
1637  MasterAdapter = AdapterObject->MasterAdapter;
1638 
1639  for (;;)
1640  {
1641  /*
1642  * To keep map registers, call here with AdapterObject->
1643  * NumberOfMapRegisters set to zero. This trick is used in
1644  * HalAllocateAdapterChannel for example.
1645  */
1646  if (AdapterObject->NumberOfMapRegisters)
1647  {
1648  IoFreeMapRegisters(AdapterObject,
1649  AdapterObject->MapRegisterBase,
1650  AdapterObject->NumberOfMapRegisters);
1651  }
1652 
1653  DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
1654  if (!DeviceQueueEntry) break;
1655 
1656  WaitContextBlock = CONTAINING_RECORD(DeviceQueueEntry,
1658  WaitQueueEntry);
1659 
1660  AdapterObject->CurrentWcb = WaitContextBlock;
1661  AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters;
1662 
1663  if ((WaitContextBlock->NumberOfMapRegisters) && (AdapterObject->MasterAdapter))
1664  {
1665  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1666 
1667  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1668  {
1669  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1670  WaitContextBlock->NumberOfMapRegisters,
1671  0);
1672  if (Index != MAXULONG)
1673  {
1674  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1675  if (!AdapterObject->ScatterGather)
1676  {
1677  AdapterObject->MapRegisterBase =(PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1678  }
1679  }
1680  }
1681 
1682  if (Index == MAXULONG)
1683  {
1684  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1685  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1686  break;
1687  }
1688 
1689  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1690  }
1691  else
1692  {
1693  AdapterObject->MapRegisterBase = NULL;
1694  AdapterObject->NumberOfMapRegisters = 0;
1695  }
1696 
1697  /* Call the adapter control routine. */
1698  Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject,
1699  WaitContextBlock->CurrentIrp,
1700  AdapterObject->MapRegisterBase,
1701  WaitContextBlock->DeviceContext);
1702  switch (Result)
1703  {
1704  case KeepObject:
1705  /*
1706  * We're done until the caller manually calls IoFreeAdapterChannel
1707  * or IoFreeMapRegisters.
1708  */
1709  return;
1710 
1712  /*
1713  * Hide the map registers so they aren't deallocated next time
1714  * around.
1715  */
1716  AdapterObject->NumberOfMapRegisters = 0;
1717  break;
1718 
1719  default:
1720  break;
1721  }
1722  }
1723 }
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
PDRIVER_CONTROL DeviceRoutine
Definition: iotypes.h:219
#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:65
UCHAR KIRQL
Definition: env_spec_w32.h:591
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
_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)
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
_In_ WDFCOLLECTION _In_ ULONG Index
_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
#define MAP_BASE_SW_SG
Definition: haldma.h:367
PKDEVICE_QUEUE_ENTRY NTAPI KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:153
#define NULL
Definition: types.h:112
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
unsigned int ULONG
Definition: retypes.h:1
DRIVER_CONTROL * PDRIVER_CONTROL
Definition: iotypes.h:215
_Inout_ PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
Definition: kefuncs.h:339
ULONG NumberOfMapRegisters
Definition: iotypes.h:221

◆ IoFreeMapRegisters()

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

Definition at line 1741 of file dma.c.

1744 {
1745  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
1746  PLIST_ENTRY ListEntry;
1747  KIRQL OldIrql;
1748  ULONG Index;
1749  ULONG Result;
1750 
1752 
1753  if (!(MasterAdapter) || !(MapRegisterBase)) return;
1754 
1755  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1756 
1757  if (NumberOfMapRegisters != 0)
1758  {
1759  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1760 
1761  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1762  RtlClearBits(MasterAdapter->MapRegisters,
1763  (ULONG)(RealMapRegisterBase - MasterAdapter->MapRegisterBase),
1765  }
1766 
1767  /*
1768  * Now that we freed few map registers it's time to look at the master
1769  * adapter queue and see if there is someone waiting for map registers.
1770  */
1771  while (!IsListEmpty(&MasterAdapter->AdapterQueue))
1772  {
1773  ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue);
1774  AdapterObject = CONTAINING_RECORD(ListEntry, struct _ADAPTER_OBJECT, AdapterQueue);
1775 
1776  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1777  AdapterObject->NumberOfMapRegisters,
1778  0);
1779  if (Index == MAXULONG)
1780  {
1781  InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
1782  break;
1783  }
1784 
1785  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1786 
1787  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1788  if (!AdapterObject->ScatterGather)
1789  {
1790  AdapterObject->MapRegisterBase =
1791  (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1792  }
1793 
1794  Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(AdapterObject->CurrentWcb->DeviceObject,
1795  AdapterObject->CurrentWcb->CurrentIrp,
1796  AdapterObject->MapRegisterBase,
1797  AdapterObject->CurrentWcb->DeviceContext);
1798  switch (Result)
1799  {
1801  AdapterObject->NumberOfMapRegisters = 0;
1802  /* fall through */
1803 
1804  case DeallocateObject:
1805  if (AdapterObject->NumberOfMapRegisters)
1806  {
1807  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1808  RtlClearBits(MasterAdapter->MapRegisters,
1809  (ULONG)(AdapterObject->MapRegisterBase -
1810  MasterAdapter->MapRegisterBase),
1811  AdapterObject->NumberOfMapRegisters);
1812  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1813  }
1814 
1815  IoFreeAdapterChannel(AdapterObject);
1816  break;
1817 
1818  default:
1819  break;
1820  }
1821 
1822  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1823  }
1824 
1825  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1826 }
#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
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint32_t ULONG_PTR
Definition: typedefs.h:65
UCHAR KIRQL
Definition: env_spec_w32.h:591
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
_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
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
#define ASSERT(a)
Definition: mode.c:44
_In_ WDFCOLLECTION _In_ ULONG Index
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
Definition: typedefs.h:119
#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:212
#define MAP_BASE_SW_SG
Definition: haldma.h:367
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
unsigned int ULONG
Definition: retypes.h:1
DRIVER_CONTROL * PDRIVER_CONTROL
Definition: iotypes.h:215

◆ 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 2035 of file dma.c.

2041 {
2042  PPFN_NUMBER MdlPagesPtr;
2043  PFN_NUMBER MdlPage1, MdlPage2;
2044  ULONG ByteOffset;
2046  ULONG TransferLength;
2047  BOOLEAN UseMapRegisters;
2048  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
2051  ULONG Counter;
2052  DMA_MODE AdapterMode;
2053  KIRQL OldIrql;
2054 
2055  /*
2056  * Precalculate some values that are used in all cases.
2057  *
2058  * ByteOffset is offset inside the page at which the transfer starts.
2059  * MdlPagesPtr is pointer inside the MDL page chain at the page where the
2060  * transfer start.
2061  * PhysicalAddress is physical address corresponding to the transfer
2062  * start page and offset.
2063  * TransferLength is the initial length of the transfer, which is reminder
2064  * of the first page. The actual value is calculated below.
2065  *
2066  * Note that all the variables can change during the processing which
2067  * takes place below. These are just initial values.
2068  */
2069  ByteOffset = BYTE_OFFSET(CurrentVa);
2070 
2071  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
2072  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
2073 
2074  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
2076 
2077  TransferLength = PAGE_SIZE - ByteOffset;
2078 
2079  /*
2080  * Special case for bus master adapters with S/G support. We can directly
2081  * use the buffer specified by the MDL, so not much work has to be done.
2082  *
2083  * Just return the passed VA's corresponding physical address and update
2084  * length to the number of physically contiguous bytes found. Also
2085  * pages crossing the 4Gb boundary aren't considered physically contiguous.
2086  */
2087  if (MapRegisterBase == NULL)
2088  {
2089  while (TransferLength < *Length)
2090  {
2091  MdlPage1 = *MdlPagesPtr;
2092  MdlPage2 = *(MdlPagesPtr + 1);
2093  if (MdlPage1 + 1 != MdlPage2) break;
2094  if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF) break;
2095  TransferLength += PAGE_SIZE;
2096  MdlPagesPtr++;
2097  }
2098 
2099  if (TransferLength < *Length) *Length = TransferLength;
2100 
2101  return PhysicalAddress;
2102  }
2103 
2104  /*
2105  * The code below applies to slave DMA adapters and bus master adapters
2106  * without hardward S/G support.
2107  */
2108  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
2109 
2110  /*
2111  * Try to calculate the size of the transfer. We can only transfer
2112  * pages that are physically contiguous and that don't cross the
2113  * 64Kb boundary (this limitation applies only for ISA controllers).
2114  */
2115  while (TransferLength < *Length)
2116  {
2117  MdlPage1 = *MdlPagesPtr;
2118  MdlPage2 = *(MdlPagesPtr + 1);
2119  if (MdlPage1 + 1 != MdlPage2) break;
2120  if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF)) break;
2121  TransferLength += PAGE_SIZE;
2122  MdlPagesPtr++;
2123  }
2124 
2125  if (TransferLength > *Length) TransferLength = *Length;
2126 
2127  /*
2128  * If we're about to simulate software S/G and not all the pages are
2129  * physically contiguous then we must use the map registers to store
2130  * the data and allow the whole transfer to proceed at once.
2131  */
2132  if (((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) && (TransferLength < *Length))
2133  {
2134  UseMapRegisters = TRUE;
2135  PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
2137  TransferLength = *Length;
2138  RealMapRegisterBase->Counter = MAXULONG;
2139  Counter = 0;
2140  }
2141  else
2142  {
2143  /*
2144  * This is ordinary DMA transfer, so just update the progress
2145  * counters. These are used by IoFlushAdapterBuffers to track
2146  * the transfer progress.
2147  */
2148  UseMapRegisters = FALSE;
2149  Counter = RealMapRegisterBase->Counter;
2150  RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength);
2151 
2152  /*
2153  * Check if the buffer doesn't exceed the highest physical address
2154  * limit of the device. In that case we must use the map registers to
2155  * store the data.
2156  */
2158  if ((PhysicalAddress.QuadPart + TransferLength) > HighestAcceptableAddress.QuadPart)
2159  {
2160  UseMapRegisters = TRUE;
2161  PhysicalAddress = RealMapRegisterBase[Counter].PhysicalAddress;
2164  {
2165  RealMapRegisterBase->Counter = MAXULONG;
2166  Counter = 0;
2167  }
2168  }
2169  }
2170 
2171  /*
2172  * If we decided to use the map registers (see above) and we're about
2173  * to transfer data to the device then copy the buffers into the map
2174  * register memory.
2175  */
2176  if ((UseMapRegisters) && (WriteToDevice))
2177  {
2179  RealMapRegisterBase + Counter,
2180  CurrentVa,
2181  TransferLength,
2182  WriteToDevice);
2183  }
2184 
2185  /*
2186  * Return the length of transfer that actually takes place.
2187  */
2188  *Length = TransferLength;
2189 
2190  /*
2191  * If we're doing slave (system) DMA then program the (E)ISA controller
2192  * to actually start the transfer.
2193  */
2194  if ((AdapterObject) && !(AdapterObject->MasterDevice))
2195  {
2196  AdapterMode = AdapterObject->AdapterMode;
2197 
2198  if (WriteToDevice)
2199  {
2200  AdapterMode.TransferType = WRITE_TRANSFER;
2201  }
2202  else
2203  {
2204  AdapterMode.TransferType = READ_TRANSFER;
2205  if (AdapterObject->IgnoreCount)
2206  {
2207  RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress + ByteOffset,
2208  TransferLength);
2209  }
2210  }
2211 
2213  if (AdapterObject->Width16Bits)
2214  {
2215  TransferLength >>= 1;
2216  TransferOffset >>= 1;
2217  }
2218 
2219  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
2220 
2221  if (AdapterObject->AdapterNumber == 1)
2222  {
2223  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
2224 
2225  /* Reset Register */
2226  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
2227 
2228  /* Set the Mode */
2229  WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte);
2230 
2231  /* Set the Offset Register */
2232  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2233  (UCHAR)(TransferOffset));
2234  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2235  (UCHAR)(TransferOffset >> 8));
2236 
2237  /* Set the Page Register */
2238  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2239  (UCHAR)(PhysicalAddress.LowPart >> 16));
2240  if (HalpEisaDma)
2241  {
2242  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2243  0);
2244  }
2245 
2246  /* Set the Length */
2247  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2248  (UCHAR)(TransferLength - 1));
2249  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2250  (UCHAR)((TransferLength - 1) >> 8));
2251 
2252  /* Unmask the Channel */
2253  WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
2254  }
2255  else
2256  {
2257  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
2258 
2259  /* Reset Register */
2260  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
2261 
2262  /* Set the Mode */
2263  WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte);
2264 
2265  /* Set the Offset Register */
2266  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2267  (UCHAR)(TransferOffset));
2268  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2269  (UCHAR)(TransferOffset >> 8));
2270 
2271  /* Set the Page Register */
2272  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2273  (UCHAR)(PhysicalAddress.u.LowPart >> 16));
2274  if (HalpEisaDma)
2275  {
2276  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2277  0);
2278  }
2279 
2280  /* Set the Length */
2281  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2282  (UCHAR)(TransferLength - 1));
2283  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2284  (UCHAR)((TransferLength - 1) >> 8));
2285 
2286  /* Unmask the Channel */
2287  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
2288  AdapterObject->ChannelNumber | DMA_CLEARMASK);
2289  }
2290 
2291  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
2292  }
2293 
2294  /*
2295  * Return physical address of the buffer with data that is used for the
2296  * transfer. It can either point inside the Mdl that was passed by the
2297  * caller or into the map registers if the Mdl buffer can't be used
2298  * directly.
2299  */
2300  return PhysicalAddress;
2301 }
UCHAR DmaBaseCount
Definition: haldma.h:184
#define WRITE_TRANSFER
Definition: haldma.h:166
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
UCHAR DmaBaseAddress
Definition: haldma.h:183
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define MmGetMdlPfnArray(_Mdl)
UCHAR SingleMask
Definition: haldma.h:215
VOID NTAPI HalpCopyBufferMap(IN PMDL Mdl, IN PROS_MAP_REGISTER_ENTRY MapRegisterBase, IN PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice)
Definition: dma.c:1837
DMA1_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:197
#define TRUE
Definition: types.h:120
UCHAR Mode
Definition: haldma.h:217
_Must_inspect_result_ _In_ WDFUSBDEVICE _In_ WDFREQUEST _In_ PWDF_USB_CONTROL_SETUP_PACKET _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET TransferOffset
Definition: wdfusb.h:1378
unsigned char * PUCHAR
Definition: retypes.h:3
UCHAR DmaBaseAddress
Definition: haldma.h:189
Definition: haldma.h:312
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:235
UCHAR Byte
Definition: haldma.h:99
uint32_t ULONG_PTR
Definition: typedefs.h:65
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG * PPFN_NUMBER
Definition: ke.h:9
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
UCHAR SingleMask
Definition: haldma.h:200
ULONG PFN_NUMBER
Definition: ke.h:9
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
UCHAR ClearBytePointer
Definition: haldma.h:219
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
#define READ_TRANSFER
Definition: haldma.h:165
DMA2_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:210
#define BYTES_TO_PAGES(Size)
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1098
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
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
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:106
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:989
#define MAXULONG
Definition: typedefs.h:251
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:212
#define MAP_BASE_SW_SG
Definition: haldma.h:367
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NULL
Definition: types.h:112
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
static LARGE_INTEGER Counter
Definition: clock.c:43
struct _LARGE_INTEGER::@2240 u
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
UCHAR Mode
Definition: haldma.h:201
#define DMA_CLEARMASK
Definition: haldma.h:175
static BOOLEAN HalpEisaDma
Definition: dma.c:88
UCHAR ClearBytePointer
Definition: haldma.h:202
#define BYTE_OFFSET(Va)
LONGLONG QuadPart
Definition: typedefs.h:114
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:725

Variable Documentation

◆ HalpDmaAdapterList

LIST_ENTRY HalpDmaAdapterList
static

Definition at line 85 of file dma.c.

Referenced by HalGetAdapter(), and HalpInitDma().

◆ HalpDmaAdapterListLock

KSPIN_LOCK HalpDmaAdapterListLock
static

Definition at line 84 of file dma.c.

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

◆ HalpDmaLock

KEVENT HalpDmaLock
static

Definition at line 83 of file dma.c.

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

◆ HalpDmaOperations

DMA_OPERATIONS HalpDmaOperations
static
Initial value:
= {
sizeof(DMA_OPERATIONS),
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:2311
ULONG NTAPI HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:76
VOID(NTAPI * PPUT_SCATTER_GATHER_LIST)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PSCATTER_GATHER_LIST ScatterGather, _In_ BOOLEAN WriteToDevice)
Definition: iotypes.h:2391
VOID NTAPI HalPutScatterGatherList(IN PADAPTER_OBJECT AdapterObject, IN PSCATTER_GATHER_LIST ScatterGather, IN BOOLEAN WriteToDevice)
Definition: dma.c:1127
ULONG(NTAPI * PGET_DMA_ALIGNMENT)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2362
ULONG NTAPI HalpDmaGetDmaAlignment(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:1320
NTSTATUS NTAPI HalGetScatterGatherList(IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_OBJECT DeviceObject, IN PMDL Mdl, IN PVOID CurrentVa, IN ULONG Length, IN PDRIVER_LIST_CONTROL ExecutionRoutine, IN PVOID Context, IN BOOLEAN WriteToDevice)
Definition: dma.c:1086
NTSTATUS(NTAPI * PCALCULATE_SCATTER_GATHER_LIST_SIZE)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PMDL Mdl OPTIONAL, _In_ PVOID CurrentVa, _In_ ULONG Length, _Out_ PULONG ScatterGatherListSize, _Out_ OPTIONAL PULONG pNumberOfMapRegisters)
Definition: iotypes.h:2397
NTSTATUS NTAPI HalBuildMdlFromScatterGatherList(IN PDMA_ADAPTER DmaAdapter, IN PSCATTER_GATHER_LIST ScatterGather, IN PMDL OriginalMdl, OUT PMDL *TargetMdl)
Definition: dma.c:1299
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:2318
VOID(NTAPI * PPUT_DMA_ADAPTER)(PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2307
struct _DMA_OPERATIONS DMA_OPERATIONS
VOID NTAPI HalPutDmaAdapter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:35
NTSTATUS(NTAPI * PBUILD_MDL_FROM_SCATTER_GATHER_LIST)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PSCATTER_GATHER_LIST ScatterGather, _In_ PMDL OriginalMdl, _Out_ PMDL *TargetMdl)
Definition: iotypes.h:2419
NTSTATUS(NTAPI * PBUILD_SCATTER_GATHER_LIST)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PDEVICE_OBJECT DeviceObject, _In_ PMDL Mdl, _In_ PVOID CurrentVa, _In_ ULONG Length, _In_ PDRIVER_LIST_CONTROL ExecutionRoutine, _In_ PVOID Context, _In_ BOOLEAN WriteToDevice, _In_ PVOID ScatterGatherBuffer, _In_ ULONG ScatterGatherLength)
Definition: iotypes.h:2406
ULONG(NTAPI * PREAD_DMA_COUNTER)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2366
#define NULL
Definition: types.h:112
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
NTSTATUS(NTAPI * PGET_SCATTER_GATHER_LIST)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PDEVICE_OBJECT DeviceObject, _In_ PMDL Mdl, _In_ PVOID CurrentVa, _In_ ULONG Length, _In_ PDRIVER_LIST_CONTROL ExecutionRoutine, _In_ PVOID Context, _In_ BOOLEAN WriteToDevice)
Definition: iotypes.h:2380
NTSTATUS NTAPI HalBuildScatterGatherList(IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_OBJECT DeviceObject, IN PMDL Mdl, IN PVOID CurrentVa, IN ULONG Length, IN PDRIVER_LIST_CONTROL ExecutionRoutine, IN PVOID Context, IN BOOLEAN WriteToDevice, IN PVOID ScatterGatherBuffer, IN ULONG ScatterGatherLength)
Definition: dma.c:1219
NTSTATUS NTAPI HalCalculateScatterGatherListSize(IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl OPTIONAL, IN PVOID CurrentVa, IN ULONG Length, OUT PULONG ScatterGatherListSize, OUT PULONG pNumberOfMapRegisters)
Definition: dma.c:1161

Definition at line 138 of file dma.c.

Referenced by HalpDmaAllocateChildAdapter(), and HalpInitDma().

◆ HalpEisaAdapter

PADAPTER_OBJECT HalpEisaAdapter[8]
static

Definition at line 86 of file dma.c.

Referenced by HalGetAdapter().

◆ HalpEisaDma

BOOLEAN HalpEisaDma
static

Definition at line 88 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 93 of file dma.c.

Referenced by HalpDmaInitializeEisaAdapter().

◆ HalpMasterAdapter

PADAPTER_OBJECT HalpMasterAdapter
static

Definition at line 90 of file dma.c.

Referenced by HalpDmaAllocateChildAdapter(), and HalpInitDma().