ReactOS  0.4.15-dev-5079-gf79e80c
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 1461 of file dma.c.

1465 {
1466  PADAPTER_OBJECT MasterAdapter;
1468  ULONG Index = MAXULONG;
1469  ULONG Result;
1470  KIRQL OldIrql;
1471 
1473 
1474  /* Set up the wait context block in case we can't run right away. */
1475  WaitContextBlock->DeviceRoutine = ExecutionRoutine;
1476  WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
1477 
1478  /* Returns true if queued, else returns false and sets the queue to busy */
1479  if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue,
1480  &WaitContextBlock->WaitQueueEntry))
1481  {
1482  return STATUS_SUCCESS;
1483  }
1484 
1485  MasterAdapter = AdapterObject->MasterAdapter;
1486 
1487  AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
1488  AdapterObject->CurrentWcb = WaitContextBlock;
1489 
1490  if ((NumberOfMapRegisters) && (AdapterObject->NeedsMapRegisters))
1491  {
1492  if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
1493  {
1494  AdapterObject->NumberOfMapRegisters = 0;
1495  IoFreeAdapterChannel(AdapterObject);
1497  }
1498 
1499  /*
1500  * Get the map registers. This is partly complicated by the fact
1501  * that new map registers can only be allocated at PASSIVE_LEVEL
1502  * and we're currently at DISPATCH_LEVEL. The following code has
1503  * two code paths:
1504  *
1505  * - If there is no adapter queued for map register allocation,
1506  * try to see if enough contiguous map registers are present.
1507  * In case they're we can just get them and proceed further.
1508  *
1509  * - If some adapter is already present in the queue we must
1510  * respect the order of adapters asking for map registers and
1511  * so the fast case described above can't take place.
1512  * This case is also entered if not enough coniguous map
1513  * registers are present.
1514  *
1515  * A work queue item is allocated and queued, the adapter is
1516  * also queued into the master adapter queue. The worker
1517  * routine does the job of allocating the map registers at
1518  * PASSIVE_LEVEL and calling the ExecutionRoutine.
1519  */
1520 
1521  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1522 
1523  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1524  {
1525  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, NumberOfMapRegisters, 0);
1526  if (Index != MAXULONG)
1527  {
1528  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1529  if (!AdapterObject->ScatterGather)
1530  {
1531  AdapterObject->MapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1532  }
1533  }
1534  }
1535 
1536  if (Index == MAXULONG)
1537  {
1538  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1539 
1541  sizeof(GROW_WORK_ITEM),
1542  TAG_DMA);
1543  if (WorkItem)
1544  {
1546  WorkItem->AdapterObject = AdapterObject;
1547  WorkItem->NumberOfMapRegisters = NumberOfMapRegisters;
1548 
1549  ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue);
1550  }
1551 
1552  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1553 
1554  return STATUS_SUCCESS;
1555  }
1556 
1557  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1558  }
1559  else
1560  {
1561  AdapterObject->MapRegisterBase = NULL;
1562  AdapterObject->NumberOfMapRegisters = 0;
1563  }
1564 
1565  AdapterObject->CurrentWcb = WaitContextBlock;
1566 
1567  Result = ExecutionRoutine(WaitContextBlock->DeviceObject,
1568  WaitContextBlock->CurrentIrp,
1569  AdapterObject->MapRegisterBase,
1570  WaitContextBlock->DeviceContext);
1571 
1572  /*
1573  * Possible return values:
1574  *
1575  * - KeepObject
1576  * Don't free any resources, the ADAPTER_OBJECT is still in use and
1577  * the caller will call IoFreeAdapterChannel later.
1578  *
1579  * - DeallocateObject
1580  * Deallocate the map registers and release the ADAPTER_OBJECT, so
1581  * someone else can use it.
1582  *
1583  * - DeallocateObjectKeepRegisters
1584  * Release the ADAPTER_OBJECT, but hang on to the map registers. The
1585  * client will later call IoFreeMapRegisters.
1586  *
1587  * NOTE:
1588  * IoFreeAdapterChannel runs the queue, so it must be called unless
1589  * the adapter object is not to be freed.
1590  */
1591  if (Result == DeallocateObject)
1592  {
1593  IoFreeAdapterChannel(AdapterObject);
1594  }
1596  {
1597  AdapterObject->NumberOfMapRegisters = 0;
1598  IoFreeAdapterChannel(AdapterObject);
1599  }
1600 
1601  return STATUS_SUCCESS;
1602 }
#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:1402
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:792
#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 909 of file dma.c.

913 {
916  PHYSICAL_ADDRESS BoundryAddressMultiple;
918 
921  BoundryAddressMultiple.QuadPart = 0;
922 
923  /*
924  * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For
925  * slave DMA devices the 64Kb boundary mustn't be crossed since the
926  * controller wouldn't be able to handle it.
927  */
928  if (AdapterObject->MasterDevice)
929  {
930  BoundryAddressMultiple.HighPart = 1;
931  }
932  else
933  {
934  BoundryAddressMultiple.LowPart = 0x10000;
935  }
936 
940  BoundryAddressMultiple,
941  CacheEnabled ? MmCached :
942  MmNonCached);
943  if (VirtualAddress == NULL) return NULL;
944 
945  *LogicalAddress = MmGetPhysicalAddress(VirtualAddress);
946 
947  return VirtualAddress;
948 }
_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 2321 of file dma.c.

2323 {
2324  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
2325  ULONG MapRegisterNumber;
2326 
2327  /* Check if it needs map registers */
2328  if (AdapterObject->NeedsMapRegisters)
2329  {
2330  /* Check if we have enough */
2331  if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
2332  {
2333  /* We don't, fail */
2334  AdapterObject->NumberOfMapRegisters = 0;
2335  return NULL;
2336  }
2337 
2338  /* Try to find free map registers */
2339  MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
2341  0);
2342 
2343  /* Check if nothing was found */
2344  if (MapRegisterNumber == MAXULONG)
2345  {
2346  /* No free registers found, so use the base registers */
2347  RtlSetBits(MasterAdapter->MapRegisters,
2348  0,
2350  MapRegisterNumber = 0;
2351  }
2352 
2353  /* Calculate the new base */
2354  AdapterObject->MapRegisterBase =
2355  (PROS_MAP_REGISTER_ENTRY)(MasterAdapter->MapRegisterBase +
2356  MapRegisterNumber);
2357 
2358  /* Check if scatter gather isn't supported */
2359  if (!AdapterObject->ScatterGather)
2360  {
2361  /* Set the flag */
2362  AdapterObject->MapRegisterBase =
2364  ((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
2365  }
2366  }
2367  else
2368  {
2369  AdapterObject->MapRegisterBase = NULL;
2370  AdapterObject->NumberOfMapRegisters = 0;
2371  }
2372 
2373  /* Return the base */
2374  return AdapterObject->MapRegisterBase;
2375 }
_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 1295 of file dma.c.

1300 {
1301  UNIMPLEMENTED;
1302  return STATUS_NOT_IMPLEMENTED;
1303 }
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 1215 of file dma.c.

1226 {
1227  NTSTATUS Status;
1228  ULONG SgSize, NumberOfMapRegisters;
1229  PSCATTER_GATHER_CONTEXT ScatterGatherContext;
1230  BOOLEAN UsingUserBuffer;
1231 
1232  Status = HalCalculateScatterGatherListSize(AdapterObject,
1233  Mdl,
1234  CurrentVa,
1235  Length,
1236  &SgSize,
1238  if (!NT_SUCCESS(Status)) return Status;
1239 
1240  if (ScatterGatherBuffer)
1241  {
1242  /* Checking if user buffer is enough */
1243  if (ScatterGatherBufferLength < SgSize)
1244  {
1245  return STATUS_BUFFER_TOO_SMALL;
1246  }
1247  UsingUserBuffer = TRUE;
1248  }
1249  else
1250  {
1251  ScatterGatherBuffer = ExAllocatePoolWithTag(NonPagedPool, SgSize, TAG_DMA);
1252  if (!ScatterGatherBuffer)
1253  {
1255  }
1256  UsingUserBuffer = FALSE;
1257  }
1258 
1259  {
1260  ScatterGatherContext = (PSCATTER_GATHER_CONTEXT)ScatterGatherBuffer;
1261 
1262  /* Fill the scatter-gather context */
1263  ScatterGatherContext->UsingUserBuffer = UsingUserBuffer;
1264  ScatterGatherContext->AdapterObject = AdapterObject;
1265  ScatterGatherContext->Mdl = Mdl;
1266  ScatterGatherContext->CurrentVa = CurrentVa;
1267  ScatterGatherContext->Length = Length;
1268  ScatterGatherContext->MapRegisterCount = NumberOfMapRegisters;
1269  ScatterGatherContext->AdapterListControlRoutine = ExecutionRoutine;
1270  ScatterGatherContext->AdapterListControlContext = Context;
1271  ScatterGatherContext->WriteToDevice = WriteToDevice;
1272 
1273  ScatterGatherContext->Wcb.DeviceObject = DeviceObject;
1274  ScatterGatherContext->Wcb.DeviceContext = (PVOID)ScatterGatherContext;
1275  ScatterGatherContext->Wcb.CurrentIrp = DeviceObject->CurrentIrp;
1276 
1277  Status = HalAllocateAdapterChannel(AdapterObject,
1278  &ScatterGatherContext->Wcb,
1281 
1282  if (!NT_SUCCESS(Status))
1283  {
1284  if (!UsingUserBuffer)
1285  ExFreePoolWithTag(ScatterGatherBuffer, TAG_DMA);
1286  return Status;
1287  }
1288  }
1289 
1290  return STATUS_SUCCESS;
1291 }
PDRIVER_LIST_CONTROL AdapterListControlRoutine
Definition: dma.c:978
#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:980
#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:974
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOLEAN UsingUserBuffer
Definition: dma.c:973
#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:982
_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:979
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:988
#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:981
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:1157

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

1164 {
1166  ULONG SgSize;
1167 
1169 
1171  SgSize = sizeof(SCATTER_GATHER_CONTEXT);
1172 
1173  *ScatterGatherListSize = SgSize;
1174  if (pNumberOfMapRegisters) *pNumberOfMapRegisters = NumberOfMapRegisters;
1175 
1176  return STATUS_SUCCESS;
1177 }
#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 2307 of file dma.c.

2311 {
2312  /* Function always returns true */
2313  return TRUE;
2314 }
#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 961 of file dma.c.

966 {
968  Length,
969  CacheEnabled ? MmCached : MmNonCached);
970 }
_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 661 of file dma.c.

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

1090 {
1091  return HalBuildScatterGatherList(AdapterObject,
1092  DeviceObject,
1093  Mdl,
1094  CurrentVa,
1095  Length,
1097  Context,
1098  WriteToDevice,
1099  NULL,
1100  0);
1101 }
_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:1215

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

1838 {
1839  ULONG CurrentLength;
1840  ULONG_PTR CurrentAddress;
1841  ULONG ByteOffset;
1843 
1845  if (!VirtualAddress)
1846  {
1847  /*
1848  * NOTE: On real NT a mechanism with reserved pages is implemented
1849  * to handle this case in a slow, but graceful non-fatal way.
1850  */
1851  KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0);
1852  }
1853 
1854  CurrentAddress = (ULONG_PTR)VirtualAddress +
1855  (ULONG_PTR)CurrentVa -
1857 
1858  while (Length > 0)
1859  {
1860  ByteOffset = BYTE_OFFSET(CurrentAddress);
1861  CurrentLength = PAGE_SIZE - ByteOffset;
1862  if (CurrentLength > Length) CurrentLength = Length;
1863 
1864  if (WriteToDevice)
1865  {
1866  RtlCopyMemory((PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1867  (PVOID)CurrentAddress,
1868  CurrentLength);
1869  }
1870  else
1871  {
1872  RtlCopyMemory((PVOID)CurrentAddress,
1873  (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1874  CurrentLength);
1875  }
1876 
1877  Length -= CurrentLength;
1878  CurrentAddress += CurrentLength;
1879  MapRegisterBase++;
1880  }
1881 }
_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  RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
481 
482  Status = ObInsertObject(AdapterObject,
483  NULL,
485  0,
486  NULL,
487  &Handle);
488  if (!NT_SUCCESS(Status)) return NULL;
489 
490  ObReferenceObject(AdapterObject);
491 
492  ZwClose(Handle);
493 
494  AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version;
495  AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT);
496  AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations;
497  AdapterObject->MapRegistersPerChannel = 1;
498  AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
499  AdapterObject->ChannelNumber = 0xFF;
500  AdapterObject->MasterAdapter = HalpMasterAdapter;
501  KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
502 
503  return AdapterObject;
504 }
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
#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:951
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:2935
unsigned short USHORT
Definition: pedump.c:61
#define NULL
Definition: types.h:112
_In_ HANDLE Handle
Definition: extypes.h:390
#define ObReferenceObject
Definition: obfuncs.h:204
#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:240
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 1316 of file dma.c.

1317 {
1318  return 1;
1319 }

◆ HalpDmaInitializeEisaAdapter()

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

Definition at line 514 of file dma.c.

516 {
517  UCHAR Controller;
518  DMA_MODE DmaMode = {{0 }};
519  DMA_EXTENDED_MODE ExtendedMode = {{ 0 }};
520  PVOID AdapterBaseVa;
521 
522  Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1;
523 
524  if (Controller == 1)
525  {
526  AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController1));
527  }
528  else
529  {
530  AdapterBaseVa = UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2));
531  }
532 
533  AdapterObject->AdapterNumber = Controller;
534  AdapterObject->ChannelNumber = (UCHAR)(DeviceDescription->DmaChannel & 3);
535  AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel];
536  AdapterObject->Width16Bits = FALSE;
537  AdapterObject->AdapterBaseVa = AdapterBaseVa;
538 
539  if (HalpEisaDma)
540  {
541  ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber;
542 
543  switch (DeviceDescription->DmaSpeed)
544  {
545  case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break;
546  case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break;
547  case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break;
548  case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break;
549  default:
550  return FALSE;
551  }
552 
553  switch (DeviceDescription->DmaWidth)
554  {
555  case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break;
556  case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break;
557  case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break;
558  default:
559  return FALSE;
560  }
561 
562  if (Controller == 1)
563  {
565  ExtendedMode.Byte);
566  }
567  else
568  {
570  ExtendedMode.Byte);
571  }
572  }
573  else
574  {
575  /*
576  * Validate setup for non-busmaster DMA adapter. Secondary controller
577  * supports only 16-bit transfers and main controller supports only
578  * 8-bit transfers. Anything else is invalid.
579  */
580  if (!DeviceDescription->Master)
581  {
582  if ((Controller == 2) && (DeviceDescription->DmaWidth == Width16Bits))
583  {
584  AdapterObject->Width16Bits = TRUE;
585  }
586  else if ((Controller != 1) || (DeviceDescription->DmaWidth != Width8Bits))
587  {
588  return FALSE;
589  }
590  }
591  }
592 
593  DmaMode.Channel = AdapterObject->ChannelNumber;
594  DmaMode.AutoInitialize = DeviceDescription->AutoInitialize;
595 
596  /*
597  * Set the DMA request mode.
598  *
599  * For (E)ISA bus master devices just unmask (enable) the DMA channel
600  * and set it to cascade mode. Otherwise just select the right one
601  * bases on the passed device description.
602  */
603  if (DeviceDescription->Master)
604  {
606  if (Controller == 1)
607  {
608  /* Set the Request Data */
610  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
611 
612  /* Unmask DMA Channel */
613  WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask,
614  AdapterObject->ChannelNumber | DMA_CLEARMASK);
615  }
616  else
617  {
618  /* Set the Request Data */
619  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
620 
621  /* Unmask DMA Channel */
622  WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask,
623  AdapterObject->ChannelNumber | DMA_CLEARMASK);
624  }
625  }
626  else
627  {
628  if (DeviceDescription->DemandMode)
629  {
631  }
632  else
633  {
635  }
636  }
637 
638  AdapterObject->AdapterMode = DmaMode;
639 
640  return TRUE;
641 }
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 852 of file dma.c.

855 {
857 }
_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:792
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 1402 of file dma.c.

1403 {
1405  KIRQL OldIrql;
1406  BOOLEAN Succeeded;
1407 
1408  /*
1409  * Try to allocate new map registers for the adapter.
1410  *
1411  * NOTE: The NT implementation actually tries to allocate more map
1412  * registers than needed as an optimization.
1413  */
1415  Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter,
1416  WorkItem->NumberOfMapRegisters << PAGE_SHIFT);
1417  KeSetEvent(&HalpDmaLock, 0, 0);
1418 
1419  if (Succeeded)
1420  {
1421  /*
1422  * Flush the adapter queue now that new map registers are ready. The
1423  * easiest way to do that is to call IoFreeMapRegisters to not free
1424  * any registers. Note that we use the magic (PVOID)2 map register
1425  * base to bypass the parameter checking.
1426  */
1428  IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
1430  }
1431 
1433 }
#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:792
#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:302
#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:852
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:240
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 988 of file dma.c.

992 {
993  PSCATTER_GATHER_CONTEXT AdapterControlContext = Context;
994  PADAPTER_OBJECT AdapterObject = AdapterControlContext->AdapterObject;
995  PSCATTER_GATHER_LIST ScatterGatherList;
997  ULONG ElementCount = 0, RemainingLength = AdapterControlContext->Length;
998  PUCHAR CurrentVa = AdapterControlContext->CurrentVa;
999 
1000  /* Store the map register base for later in HalPutScatterGatherList */
1001  AdapterControlContext->MapRegisterBase = MapRegisterBase;
1002 
1003  while (RemainingLength > 0 && ElementCount < MAX_SG_ELEMENTS)
1004  {
1005  TempElements[ElementCount].Length = RemainingLength;
1006  TempElements[ElementCount].Reserved = 0;
1007  TempElements[ElementCount].Address = IoMapTransfer(AdapterObject,
1008  AdapterControlContext->Mdl,
1010  CurrentVa + (AdapterControlContext->Length - RemainingLength),
1011  &TempElements[ElementCount].Length,
1012  AdapterControlContext->WriteToDevice);
1013  if (TempElements[ElementCount].Length == 0)
1014  break;
1015 
1016  DPRINT("Allocated one S/G element: 0x%I64u with length: 0x%x\n",
1017  TempElements[ElementCount].Address.QuadPart,
1018  TempElements[ElementCount].Length);
1019 
1020  ASSERT(TempElements[ElementCount].Length <= RemainingLength);
1021  RemainingLength -= TempElements[ElementCount].Length;
1022  ElementCount++;
1023  }
1024 
1025  if (RemainingLength > 0)
1026  {
1027  DPRINT1("Scatter/gather list construction failed!\n");
1028  return DeallocateObject;
1029  }
1030 
1031  ScatterGatherList = ExAllocatePoolWithTag(NonPagedPool,
1032  sizeof(SCATTER_GATHER_LIST) + sizeof(SCATTER_GATHER_ELEMENT) * ElementCount,
1033  TAG_DMA);
1034  ASSERT(ScatterGatherList);
1035 
1036  ScatterGatherList->NumberOfElements = ElementCount;
1037  ScatterGatherList->Reserved = (ULONG_PTR)AdapterControlContext;
1038  RtlCopyMemory(ScatterGatherList->Elements,
1039  TempElements,
1040  sizeof(SCATTER_GATHER_ELEMENT) * ElementCount);
1041 
1042  DPRINT("Initiating S/G DMA with %d element(s)\n", ElementCount);
1043 
1044  AdapterControlContext->AdapterListControlRoutine(DeviceObject,
1045  Irp,
1046  ScatterGatherList,
1047  AdapterControlContext->AdapterListControlContext);
1048 
1050 }
PDRIVER_LIST_CONTROL AdapterListControlRoutine
Definition: dma.c:978
#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:974
#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:979
_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:979
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:981

Referenced by HalBuildScatterGatherList().

◆ HalPutDmaAdapter()

VOID NTAPI HalPutDmaAdapter ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 869 of file dma.c.

870 {
871  KIRQL OldIrql;
872  if (AdapterObject->ChannelNumber == 0xFF)
873  {
875  RemoveEntryList(&AdapterObject->AdapterList);
877  }
878 
879  ObDereferenceObject(AdapterObject);
880 }
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:792
#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 1123 of file dma.c.

1126 {
1127  PSCATTER_GATHER_CONTEXT AdapterControlContext = (PSCATTER_GATHER_CONTEXT)ScatterGather->Reserved;
1128  ULONG i;
1129 
1130  for (i = 0; i < ScatterGather->NumberOfElements; i++)
1131  {
1132  IoFlushAdapterBuffers(AdapterObject,
1133  AdapterControlContext->Mdl,
1134  AdapterControlContext->MapRegisterBase,
1135  AdapterControlContext->CurrentVa,
1136  ScatterGather->Elements[i].Length,
1137  AdapterControlContext->WriteToDevice);
1138  AdapterControlContext->CurrentVa += ScatterGather->Elements[i].Length;
1139  }
1140 
1141  IoFreeMapRegisters(AdapterObject,
1142  AdapterControlContext->MapRegisterBase,
1143  AdapterControlContext->MapRegisterCount);
1144 
1145 
1147 
1148  /* If this is our buffer, release it */
1149  if (!AdapterControlContext->UsingUserBuffer)
1150  ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
1151 
1152  DPRINT("S/G DMA has finished!\n");
1153 }
ULONG MapRegisterCount
Definition: dma.c:980
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:973
#define TAG_DMA
Definition: dma.c:160
PVOID MapRegisterBase
Definition: dma.c:979
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:981

◆ HalReadDmaCounter()

ULONG NTAPI HalReadDmaCounter ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 1330 of file dma.c.

1331 {
1332  KIRQL OldIrql;
1333  ULONG Count, OldCount;
1334 
1335  ASSERT(!AdapterObject->MasterDevice);
1336 
1337  /*
1338  * Acquire the master adapter lock since we're going to mess with the
1339  * system DMA controller registers and we really don't want anyone
1340  * to do the same at the same time.
1341  */
1342  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
1343 
1344  /* Send the request to the specific controller. */
1345  if (AdapterObject->AdapterNumber == 1)
1346  {
1347  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1348 
1349  Count = 0xffff00;
1350  do
1351  {
1352  OldCount = Count;
1353 
1354  /* Send Reset */
1355  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
1356 
1357  /* Read Count */
1358  Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1359  [AdapterObject->ChannelNumber].DmaBaseCount);
1360  Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1361  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1362  } while (0xffff00 & (OldCount ^ Count));
1363  }
1364  else
1365  {
1366  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1367 
1368  Count = 0xffff00;
1369  do
1370  {
1371  OldCount = Count;
1372 
1373  /* Send Reset */
1374  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
1375 
1376  /* Read Count */
1377  Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1378  [AdapterObject->ChannelNumber].DmaBaseCount);
1379  Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1380  [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1381  } while (0xffff00 & (OldCount ^ Count));
1382  }
1383 
1384  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
1385 
1386  Count++;
1387  Count &= 0xffff;
1388  if (AdapterObject->Width16Bits) Count *= 2;
1389 
1390  return Count;
1391 }
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:792
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 1916 of file dma.c.

1922 {
1923  BOOLEAN SlaveDma = FALSE;
1924  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1927  PPFN_NUMBER MdlPagesPtr;
1928 
1929  /* Sanity checks */
1931  ASSERT(AdapterObject);
1932 
1933  if (!AdapterObject->MasterDevice)
1934  {
1935  /* Mask out (disable) the DMA channel. */
1936  if (AdapterObject->AdapterNumber == 1)
1937  {
1938  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1939  WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
1940  AdapterObject->ChannelNumber | DMA_SETMASK);
1941  }
1942  else
1943  {
1944  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1945  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
1946  AdapterObject->ChannelNumber | DMA_SETMASK);
1947  }
1948  SlaveDma = TRUE;
1949  }
1950 
1951  /* This can happen if the device supports hardware scatter/gather. */
1952  if (MapRegisterBase == NULL) return TRUE;
1953 
1954  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1955 
1956  if (!WriteToDevice)
1957  {
1959  {
1960  if (RealMapRegisterBase->Counter != MAXULONG)
1961  {
1962  if ((SlaveDma) && !(AdapterObject->IgnoreCount))
1963  {
1964  Length -= HalReadDmaCounter(AdapterObject);
1965  }
1966  }
1968  RealMapRegisterBase,
1969  CurrentVa,
1970  Length,
1971  FALSE);
1972  }
1973  else
1974  {
1975  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1976  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1977 
1978  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1979  PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa);
1980 
1983  {
1985  RealMapRegisterBase,
1986  CurrentVa,
1987  Length,
1988  FALSE);
1989  }
1990  }
1991  }
1992 
1993  RealMapRegisterBase->Counter = 0;
1994 
1995  return TRUE;
1996 }
#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:1833
#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 1624 of file dma.c.

1625 {
1626  PADAPTER_OBJECT MasterAdapter;
1628  PWAIT_CONTEXT_BLOCK WaitContextBlock;
1629  ULONG Index = MAXULONG;
1630  ULONG Result;
1631  KIRQL OldIrql;
1632 
1633  MasterAdapter = AdapterObject->MasterAdapter;
1634 
1635  for (;;)
1636  {
1637  /*
1638  * To keep map registers, call here with AdapterObject->
1639  * NumberOfMapRegisters set to zero. This trick is used in
1640  * HalAllocateAdapterChannel for example.
1641  */
1642  if (AdapterObject->NumberOfMapRegisters)
1643  {
1644  IoFreeMapRegisters(AdapterObject,
1645  AdapterObject->MapRegisterBase,
1646  AdapterObject->NumberOfMapRegisters);
1647  }
1648 
1649  DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
1650  if (!DeviceQueueEntry) break;
1651 
1652  WaitContextBlock = CONTAINING_RECORD(DeviceQueueEntry,
1654  WaitQueueEntry);
1655 
1656  AdapterObject->CurrentWcb = WaitContextBlock;
1657  AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters;
1658 
1659  if ((WaitContextBlock->NumberOfMapRegisters) && (AdapterObject->MasterAdapter))
1660  {
1661  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1662 
1663  if (IsListEmpty(&MasterAdapter->AdapterQueue))
1664  {
1665  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1666  WaitContextBlock->NumberOfMapRegisters,
1667  0);
1668  if (Index != MAXULONG)
1669  {
1670  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1671  if (!AdapterObject->ScatterGather)
1672  {
1673  AdapterObject->MapRegisterBase =(PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1674  }
1675  }
1676  }
1677 
1678  if (Index == MAXULONG)
1679  {
1680  InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1681  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1682  break;
1683  }
1684 
1685  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1686  }
1687  else
1688  {
1689  AdapterObject->MapRegisterBase = NULL;
1690  AdapterObject->NumberOfMapRegisters = 0;
1691  }
1692 
1693  /* Call the adapter control routine. */
1694  Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject,
1695  WaitContextBlock->CurrentIrp,
1696  AdapterObject->MapRegisterBase,
1697  WaitContextBlock->DeviceContext);
1698  switch (Result)
1699  {
1700  case KeepObject:
1701  /*
1702  * We're done until the caller manually calls IoFreeAdapterChannel
1703  * or IoFreeMapRegisters.
1704  */
1705  return;
1706 
1708  /*
1709  * Hide the map registers so they aren't deallocated next time
1710  * around.
1711  */
1712  AdapterObject->NumberOfMapRegisters = 0;
1713  break;
1714 
1715  default:
1716  break;
1717  }
1718  }
1719 }
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:792
#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:341
ULONG NumberOfMapRegisters
Definition: iotypes.h:221

◆ IoFreeMapRegisters()

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

Definition at line 1737 of file dma.c.

1740 {
1741  PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
1742  PLIST_ENTRY ListEntry;
1743  KIRQL OldIrql;
1744  ULONG Index;
1745  ULONG Result;
1746 
1748 
1749  if (!(MasterAdapter) || !(MapRegisterBase)) return;
1750 
1751  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1752 
1753  if (NumberOfMapRegisters != 0)
1754  {
1755  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1756 
1757  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1758  RtlClearBits(MasterAdapter->MapRegisters,
1759  (ULONG)(RealMapRegisterBase - MasterAdapter->MapRegisterBase),
1761  }
1762 
1763  /*
1764  * Now that we freed few map registers it's time to look at the master
1765  * adapter queue and see if there is someone waiting for map registers.
1766  */
1767  while (!IsListEmpty(&MasterAdapter->AdapterQueue))
1768  {
1769  ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue);
1770  AdapterObject = CONTAINING_RECORD(ListEntry, struct _ADAPTER_OBJECT, AdapterQueue);
1771 
1772  Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1773  AdapterObject->NumberOfMapRegisters,
1774  0);
1775  if (Index == MAXULONG)
1776  {
1777  InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
1778  break;
1779  }
1780 
1781  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1782 
1783  AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1784  if (!AdapterObject->ScatterGather)
1785  {
1786  AdapterObject->MapRegisterBase =
1787  (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1788  }
1789 
1790  Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(AdapterObject->CurrentWcb->DeviceObject,
1791  AdapterObject->CurrentWcb->CurrentIrp,
1792  AdapterObject->MapRegisterBase,
1793  AdapterObject->CurrentWcb->DeviceContext);
1794  switch (Result)
1795  {
1797  AdapterObject->NumberOfMapRegisters = 0;
1798  /* fall through */
1799 
1800  case DeallocateObject:
1801  if (AdapterObject->NumberOfMapRegisters)
1802  {
1803  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1804  RtlClearBits(MasterAdapter->MapRegisters,
1805  (ULONG)(AdapterObject->MapRegisterBase -
1806  MasterAdapter->MapRegisterBase),
1807  AdapterObject->NumberOfMapRegisters);
1808  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1809  }
1810 
1811  IoFreeAdapterChannel(AdapterObject);
1812  break;
1813 
1814  default:
1815  break;
1816  }
1817 
1818  KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1819  }
1820 
1821  KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1822 }
#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:792
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 2031 of file dma.c.

2037 {
2038  PPFN_NUMBER MdlPagesPtr;
2039  PFN_NUMBER MdlPage1, MdlPage2;
2040  ULONG ByteOffset;
2042  ULONG TransferLength;
2043  BOOLEAN UseMapRegisters;
2044  PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
2047  ULONG Counter;
2048  DMA_MODE AdapterMode;
2049  KIRQL OldIrql;
2050 
2051  /*
2052  * Precalculate some values that are used in all cases.
2053  *
2054  * ByteOffset is offset inside the page at which the transfer starts.
2055  * MdlPagesPtr is pointer inside the MDL page chain at the page where the
2056  * transfer start.
2057  * PhysicalAddress is physical address corresponding to the transfer
2058  * start page and offset.
2059  * TransferLength is the initial length of the transfer, which is reminder
2060  * of the first page. The actual value is calculated below.
2061  *
2062  * Note that all the variables can change during the processing which
2063  * takes place below. These are just initial values.
2064  */
2065  ByteOffset = BYTE_OFFSET(CurrentVa);
2066 
2067  MdlPagesPtr = MmGetMdlPfnArray(Mdl);
2068  MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
2069 
2070  PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
2072 
2073  TransferLength = PAGE_SIZE - ByteOffset;
2074 
2075  /*
2076  * Special case for bus master adapters with S/G support. We can directly
2077  * use the buffer specified by the MDL, so not much work has to be done.
2078  *
2079  * Just return the passed VA's corresponding physical address and update
2080  * length to the number of physically contiguous bytes found. Also
2081  * pages crossing the 4Gb boundary aren't considered physically contiguous.
2082  */
2083  if (MapRegisterBase == NULL)
2084  {
2085  while (TransferLength < *Length)
2086  {
2087  MdlPage1 = *MdlPagesPtr;
2088  MdlPage2 = *(MdlPagesPtr + 1);
2089  if (MdlPage1 + 1 != MdlPage2) break;
2090  if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF) break;
2091  TransferLength += PAGE_SIZE;
2092  MdlPagesPtr++;
2093  }
2094 
2095  if (TransferLength < *Length) *Length = TransferLength;
2096 
2097  return PhysicalAddress;
2098  }
2099 
2100  /*
2101  * The code below applies to slave DMA adapters and bus master adapters
2102  * without hardward S/G support.
2103  */
2104  RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
2105 
2106  /*
2107  * Try to calculate the size of the transfer. We can only transfer
2108  * pages that are physically contiguous and that don't cross the
2109  * 64Kb boundary (this limitation applies only for ISA controllers).
2110  */
2111  while (TransferLength < *Length)
2112  {
2113  MdlPage1 = *MdlPagesPtr;
2114  MdlPage2 = *(MdlPagesPtr + 1);
2115  if (MdlPage1 + 1 != MdlPage2) break;
2116  if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF)) break;
2117  TransferLength += PAGE_SIZE;
2118  MdlPagesPtr++;
2119  }
2120 
2121  if (TransferLength > *Length) TransferLength = *Length;
2122 
2123  /*
2124  * If we're about to simulate software S/G and not all the pages are
2125  * physically contiguous then we must use the map registers to store
2126  * the data and allow the whole transfer to proceed at once.
2127  */
2128  if (((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) && (TransferLength < *Length))
2129  {
2130  UseMapRegisters = TRUE;
2131  PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
2133  TransferLength = *Length;
2134  RealMapRegisterBase->Counter = MAXULONG;
2135  Counter = 0;
2136  }
2137  else
2138  {
2139  /*
2140  * This is ordinary DMA transfer, so just update the progress
2141  * counters. These are used by IoFlushAdapterBuffers to track
2142  * the transfer progress.
2143  */
2144  UseMapRegisters = FALSE;
2145  Counter = RealMapRegisterBase->Counter;
2146  RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength);
2147 
2148  /*
2149  * Check if the buffer doesn't exceed the highest physical address
2150  * limit of the device. In that case we must use the map registers to
2151  * store the data.
2152  */
2154  if ((PhysicalAddress.QuadPart + TransferLength) > HighestAcceptableAddress.QuadPart)
2155  {
2156  UseMapRegisters = TRUE;
2157  PhysicalAddress = RealMapRegisterBase[Counter].PhysicalAddress;
2160  {
2161  RealMapRegisterBase->Counter = MAXULONG;
2162  Counter = 0;
2163  }
2164  }
2165  }
2166 
2167  /*
2168  * If we decided to use the map registers (see above) and we're about
2169  * to transfer data to the device then copy the buffers into the map
2170  * register memory.
2171  */
2172  if ((UseMapRegisters) && (WriteToDevice))
2173  {
2175  RealMapRegisterBase + Counter,
2176  CurrentVa,
2177  TransferLength,
2178  WriteToDevice);
2179  }
2180 
2181  /*
2182  * Return the length of transfer that actually takes place.
2183  */
2184  *Length = TransferLength;
2185 
2186  /*
2187  * If we're doing slave (system) DMA then program the (E)ISA controller
2188  * to actually start the transfer.
2189  */
2190  if ((AdapterObject) && !(AdapterObject->MasterDevice))
2191  {
2192  AdapterMode = AdapterObject->AdapterMode;
2193 
2194  if (WriteToDevice)
2195  {
2196  AdapterMode.TransferType = WRITE_TRANSFER;
2197  }
2198  else
2199  {
2200  AdapterMode.TransferType = READ_TRANSFER;
2201  if (AdapterObject->IgnoreCount)
2202  {
2203  RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress + ByteOffset,
2204  TransferLength);
2205  }
2206  }
2207 
2209  if (AdapterObject->Width16Bits)
2210  {
2211  TransferLength >>= 1;
2212  TransferOffset >>= 1;
2213  }
2214 
2215  KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
2216 
2217  if (AdapterObject->AdapterNumber == 1)
2218  {
2219  PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
2220 
2221  /* Reset Register */
2222  WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
2223 
2224  /* Set the Mode */
2225  WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte);
2226 
2227  /* Set the Offset Register */
2228  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2229  (UCHAR)(TransferOffset));
2230  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2231  (UCHAR)(TransferOffset >> 8));
2232 
2233  /* Set the Page Register */
2234  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2235  (UCHAR)(PhysicalAddress.LowPart >> 16));
2236  if (HalpEisaDma)
2237  {
2238  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2239  0);
2240  }
2241 
2242  /* Set the Length */
2243  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2244  (UCHAR)(TransferLength - 1));
2245  WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2246  (UCHAR)((TransferLength - 1) >> 8));
2247 
2248  /* Unmask the Channel */
2249  WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
2250  }
2251  else
2252  {
2253  PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
2254 
2255  /* Reset Register */
2256  WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
2257 
2258  /* Set the Mode */
2259  WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte);
2260 
2261  /* Set the Offset Register */
2262  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2263  (UCHAR)(TransferOffset));
2264  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
2265  (UCHAR)(TransferOffset >> 8));
2266 
2267  /* Set the Page Register */
2268  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
2269  (UCHAR)(PhysicalAddress.u.LowPart >> 16));
2270  if (HalpEisaDma)
2271  {
2272  WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
2273  0);
2274  }
2275 
2276  /* Set the Length */
2277  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2278  (UCHAR)(TransferLength - 1));
2279  WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
2280  (UCHAR)((TransferLength - 1) >> 8));
2281 
2282  /* Unmask the Channel */
2283  WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
2284  AdapterObject->ChannelNumber | DMA_CLEARMASK);
2285  }
2286 
2287  KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
2288  }
2289 
2290  /*
2291  * Return physical address of the buffer with data that is used for the
2292  * transfer. It can either point inside the Mdl that was passed by the
2293  * caller or into the map registers if the Mdl buffer can't be used
2294  * directly.
2295  */
2296  return PhysicalAddress;
2297 }
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:1833
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
struct _LARGE_INTEGER::@2249 u
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:792
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
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:1123
ULONG(NTAPI * PGET_DMA_ALIGNMENT)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2362
ULONG NTAPI HalpDmaGetDmaAlignment(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:1316
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:1082
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:1295
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:1215
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:1157

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().