ReactOS 0.4.16-dev-2633-g8dc9e50
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   0x20
 
#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 159 of file dma.c.

◆ MAX_SG_ELEMENTS

#define MAX_SG_ELEMENTS   0x20

Definition at line 81 of file dma.c.

◆ NDEBUG

#define NDEBUG

Definition at line 77 of file dma.c.

◆ TAG_DMA

#define TAG_DMA   ' AMD'

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

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

◆ HalAllocateCommonBuffer()

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

Definition at line 910 of file dma.c.

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

◆ HalAllocateCrashDumpRegisters()

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

Definition at line 2336 of file dma.c.

2338{
2339 PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
2340 ULONG MapRegisterNumber;
2341
2342 /* Check if it needs map registers */
2343 if (AdapterObject->NeedsMapRegisters)
2344 {
2345 /* Check if we have enough */
2346 if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
2347 {
2348 /* We don't, fail */
2349 AdapterObject->NumberOfMapRegisters = 0;
2350 return NULL;
2351 }
2352
2353 /* Try to find free map registers */
2354 MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
2356 0);
2357
2358 /* Check if nothing was found */
2359 if (MapRegisterNumber == MAXULONG)
2360 {
2361 /* No free registers found, so use the base registers */
2362 RtlSetBits(MasterAdapter->MapRegisters,
2363 0,
2365 MapRegisterNumber = 0;
2366 }
2367
2368 /* Calculate the new base */
2369 AdapterObject->MapRegisterBase =
2370 (PROS_MAP_REGISTER_ENTRY)(MasterAdapter->MapRegisterBase +
2371 MapRegisterNumber);
2372
2373 /* Check if scatter gather isn't supported */
2374 if (!AdapterObject->ScatterGather)
2375 {
2376 /* Set the flag */
2377 AdapterObject->MapRegisterBase =
2379 ((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
2380 }
2381 }
2382 else
2383 {
2384 AdapterObject->MapRegisterBase = NULL;
2385 AdapterObject->NumberOfMapRegisters = 0;
2386 }
2387
2388 /* Return the base */
2389 return AdapterObject->MapRegisterBase;
2390}
#define RtlSetBits
Definition: dbgbitmap.h:345

◆ HalBuildMdlFromScatterGatherList()

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

Definition at line 1310 of file dma.c.

1315{
1318}
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42

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

1241{
1244 PSCATTER_GATHER_CONTEXT ScatterGatherContext;
1245 BOOLEAN UsingUserBuffer;
1246
1248 Mdl,
1249 CurrentVa,
1250 Length,
1251 &SgSize,
1253 if (!NT_SUCCESS(Status)) return Status;
1254
1255 if (ScatterGatherBuffer)
1256 {
1257 /* Checking if user buffer is enough */
1258 if (ScatterGatherBufferLength < SgSize)
1259 {
1261 }
1262 UsingUserBuffer = TRUE;
1263 }
1264 else
1265 {
1266 ScatterGatherBuffer = ExAllocatePoolWithTag(NonPagedPool, SgSize, TAG_DMA);
1267 if (!ScatterGatherBuffer)
1268 {
1270 }
1271 UsingUserBuffer = FALSE;
1272 }
1273
1274 {
1275 ScatterGatherContext = (PSCATTER_GATHER_CONTEXT)ScatterGatherBuffer;
1276
1277 /* Fill the scatter-gather context */
1278 ScatterGatherContext->UsingUserBuffer = UsingUserBuffer;
1279 ScatterGatherContext->AdapterObject = AdapterObject;
1280 ScatterGatherContext->Mdl = Mdl;
1281 ScatterGatherContext->CurrentVa = CurrentVa;
1282 ScatterGatherContext->Length = Length;
1283 ScatterGatherContext->MapRegisterCount = NumberOfMapRegisters;
1284 ScatterGatherContext->AdapterListControlRoutine = ExecutionRoutine;
1285 ScatterGatherContext->AdapterListControlContext = Context;
1286 ScatterGatherContext->WriteToDevice = WriteToDevice;
1287
1288 ScatterGatherContext->Wcb.DeviceObject = DeviceObject;
1289 ScatterGatherContext->Wcb.DeviceContext = (PVOID)ScatterGatherContext;
1290 ScatterGatherContext->Wcb.CurrentIrp = DeviceObject->CurrentIrp;
1291
1292 Status = HalAllocateAdapterChannel(AdapterObject,
1293 &ScatterGatherContext->Wcb,
1296
1297 if (!NT_SUCCESS(Status))
1298 {
1299 if (!UsingUserBuffer)
1300 ExFreePoolWithTag(ScatterGatherBuffer, TAG_DMA);
1301 return Status;
1302 }
1303 }
1304
1305 return STATUS_SUCCESS;
1306}
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:992
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
Status
Definition: gdiplustypes.h:25
IO_ALLOCATION_ACTION NTAPI HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context)
Definition: dma.c:989
struct _SCATTER_GATHER_CONTEXT * PSCATTER_GATHER_CONTEXT
NTSTATUS NTAPI HalAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, IN PWAIT_CONTEXT_BLOCK WaitContextBlock, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine)
Definition: dma.c:1476
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:1172
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
_In_ PVOID Context
Definition: storport.h:2269
PVOID AdapterListControlContext
Definition: dma.c:980
ULONG MapRegisterCount
Definition: dma.c:981
WAIT_CONTEXT_BLOCK Wcb
Definition: dma.c:983
PADAPTER_OBJECT AdapterObject
Definition: dma.c:975
BOOLEAN UsingUserBuffer
Definition: dma.c:974
BOOLEAN WriteToDevice
Definition: dma.c:982
PDRIVER_LIST_CONTROL AdapterListControlRoutine
Definition: dma.c:979
void * PVOID
Definition: typedefs.h:50
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl

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

1179{
1181 ULONG SgSize;
1182
1184
1186 SgSize = sizeof(SCATTER_GATHER_CONTEXT);
1187
1188 *ScatterGatherListSize = SgSize;
1189 if (pNumberOfMapRegisters) *pNumberOfMapRegisters = NumberOfMapRegisters;
1190
1191 return STATUS_SUCCESS;
1192}
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
struct _SCATTER_GATHER_CONTEXT SCATTER_GATHER_CONTEXT
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
#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 2322 of file dma.c.

2326{
2327 /* Function always returns true */
2328 return TRUE;
2329}

◆ HalFreeCommonBuffer()

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

Definition at line 962 of file dma.c.

967{
969 Length,
970 CacheEnabled ? MmCached : MmNonCached);
971}
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 662 of file dma.c.

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

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

1105{
1106 return HalBuildScatterGatherList(AdapterObject,
1108 Mdl,
1109 CurrentVa,
1110 Length,
1112 Context,
1114 NULL,
1115 0);
1116}
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:1230

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

1853{
1854 ULONG CurrentLength;
1855 ULONG_PTR CurrentAddress;
1858
1860 if (!VirtualAddress)
1861 {
1862 /*
1863 * NOTE: On real NT a mechanism with reserved pages is implemented
1864 * to handle this case in a slow, but graceful non-fatal way.
1865 */
1866 KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0);
1867 }
1868
1869 CurrentAddress = (ULONG_PTR)VirtualAddress +
1870 (ULONG_PTR)CurrentVa -
1872
1873 while (Length > 0)
1874 {
1875 ByteOffset = BYTE_OFFSET(CurrentAddress);
1876 CurrentLength = PAGE_SIZE - ByteOffset;
1877 if (CurrentLength > Length) CurrentLength = Length;
1878
1879 if (WriteToDevice)
1880 {
1882 (PVOID)CurrentAddress,
1883 CurrentLength);
1884 }
1885 else
1886 {
1887 RtlCopyMemory((PVOID)CurrentAddress,
1888 (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
1889 CurrentLength);
1890 }
1891
1892 Length -= CurrentLength;
1893 CurrentAddress += CurrentLength;
1895 }
1896}
DECLSPEC_NORETURN VOID NTAPI KeBugCheckEx(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4)
Definition: debug.c:485
#define ULONG_PTR
Definition: config.h:101
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:732
@ HighPagePriority
Definition: imports.h:55
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:213
#define MmGetMdlVirtualAddress(_Mdl)
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
#define BYTE_OFFSET(Va)

Referenced by IoFlushAdapterBuffers(), and IoMapTransfer().

◆ HalpDmaAllocateChildAdapter()

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

Definition at line 456 of file dma.c.

458{
459 PADAPTER_OBJECT AdapterObject;
463
465 NULL,
467 NULL,
468 NULL);
469
474 NULL,
475 sizeof(ADAPTER_OBJECT),
476 0,
477 0,
478 (PVOID)&AdapterObject);
479 if (!NT_SUCCESS(Status)) return NULL;
480
481 RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
482
483 Status = ObInsertObject(AdapterObject,
484 NULL,
486 0,
487 NULL,
488 &Handle);
489 if (!NT_SUCCESS(Status)) return NULL;
490
491 ObReferenceObject(AdapterObject);
492
494
495 AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version;
496 AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT);
497 AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations;
498 AdapterObject->MapRegistersPerChannel = 1;
499 AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
500 AdapterObject->ChannelNumber = 0xFF;
501 AdapterObject->MasterAdapter = HalpMasterAdapter;
502 KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
503
504 return AdapterObject;
505}
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
VOID NTAPI KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:22
ULONG Handle
Definition: gdb_input.c:15
static PADAPTER_OBJECT HalpMasterAdapter
Definition: dma.c:91
static DMA_OPERATIONS HalpDmaOperations
Definition: dma.c:139
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_READ_DATA
Definition: nt_native.h:628
POBJECT_TYPE IoAdapterObjectType
Definition: adapter.c:18
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
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:1039
unsigned short USHORT
Definition: pedump.c:61
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_PERMANENT
Definition: winternl.h:226
struct _DMA_OPERATIONS * DmaOperations
Definition: iotypes.h:2297
USHORT Size
Definition: iotypes.h:2296
USHORT Version
Definition: iotypes.h:2295
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ObReferenceObject
Definition: obfuncs.h:204

Referenced by HalGetAdapter().

◆ HalpDmaAllocateMasterAdapter()

PADAPTER_OBJECT NTAPI HalpDmaAllocateMasterAdapter ( VOID  )

Definition at line 399 of file dma.c.

400{
401 PADAPTER_OBJECT MasterAdapter;
402 ULONG Size, SizeOfBitmap;
403
404 SizeOfBitmap = MAX_MAP_REGISTERS;
405 Size = sizeof(ADAPTER_OBJECT);
406 Size += sizeof(RTL_BITMAP);
407 Size += (SizeOfBitmap + 7) >> 3;
408
410 if (!MasterAdapter) return NULL;
411
412 RtlZeroMemory(MasterAdapter, Size);
413
414 KeInitializeSpinLock(&MasterAdapter->SpinLock);
415 InitializeListHead(&MasterAdapter->AdapterQueue);
416
417 MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1);
418 RtlInitializeBitMap(MasterAdapter->MapRegisters,
419 (PULONG)(MasterAdapter->MapRegisters + 1),
420 SizeOfBitmap);
421 RtlSetAllBits(MasterAdapter->MapRegisters);
422 MasterAdapter->NumberOfMapRegisters = 0;
423 MasterAdapter->CommittedMapRegisters = 0;
424
425 MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(NonPagedPool,
426 SizeOfBitmap *
428 TAG_DMA);
429 if (!MasterAdapter->MapRegisterBase)
430 {
431 ExFreePool(MasterAdapter);
432 return NULL;
433 }
434
435 RtlZeroMemory(MasterAdapter->MapRegisterBase,
436 SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY));
437 if (!HalpGrowMapBuffers(MasterAdapter, 0x10000))
438 {
439 ExFreePool(MasterAdapter);
440 return NULL;
441 }
442
443 return MasterAdapter;
444}
#define RtlInitializeBitMap
Definition: dbgbitmap.h:326
#define RtlSetAllBits
Definition: dbgbitmap.h:346
#define RTL_BITMAP
Definition: dbgbitmap.h:323
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define MAX_MAP_REGISTERS
Definition: dma.c:159
BOOLEAN NTAPI HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject, IN ULONG SizeOfMapBuffers)
Definition: dma.c:272
struct _ADAPTER_OBJECT ADAPTER_OBJECT
Definition: haldma.h:313
uint32_t * PULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539

Referenced by HalpInitDma().

◆ HalpDmaGetDmaAlignment()

ULONG NTAPI HalpDmaGetDmaAlignment ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 1331 of file dma.c.

1332{
1333 return 1;
1334}

◆ HalpDmaInitializeEisaAdapter()

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

Definition at line 515 of file dma.c.

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

Referenced by HalGetAdapter().

◆ HalpGetAdapterMaximumPhysicalAddress()

PHYSICAL_ADDRESS NTAPI HalpGetAdapterMaximumPhysicalAddress ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 236 of file dma.c.

237{
238 PHYSICAL_ADDRESS HighestAddress;
239
240 if (AdapterObject->MasterDevice)
241 {
242 if (AdapterObject->Dma64BitAddresses)
243 {
244 HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
245 return HighestAddress;
246 }
247 else if (AdapterObject->Dma32BitAddresses)
248 {
249 HighestAddress.QuadPart = 0xFFFFFFFF;
250 return HighestAddress;
251 }
252 }
253
254 HighestAddress.QuadPart = 0xFFFFFF;
255 return HighestAddress;
256}

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

856{
858}
PADAPTER_OBJECT NTAPI HalGetAdapter(IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
Definition: dma.c:22

Referenced by HalInitSystem(), and HalpInitDma().

◆ HalpGrowMapBuffers()

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

Definition at line 272 of file dma.c.

274{
279 PHYSICAL_ADDRESS BoundryAddressMultiple;
282
283 /* Check if enough map register slots are available. */
284 MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers);
285 if (MapRegisterCount + AdapterObject->NumberOfMapRegisters > MAX_MAP_REGISTERS)
286 {
287 DPRINT("No more map register slots available! (Current: %d | Requested: %d | Limit: %d)\n",
288 AdapterObject->NumberOfMapRegisters,
291 return FALSE;
292 }
293
294 /*
295 * Allocate memory for the new map registers. For 32-bit adapters we use
296 * two passes in order not to waste scare resource (low memory).
297 */
300 LowestAcceptableAddress.LowPart = HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0;
301 BoundryAddressMultiple.QuadPart = 0;
302
306 BoundryAddressMultiple,
309 {
314 BoundryAddressMultiple,
316 }
317
318 if (!VirtualAddress) return FALSE;
319
321
322 /*
323 * All the following must be done with the master adapter lock held
324 * to prevent corruption.
325 */
326 KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql);
327
328 /*
329 * Setup map register entries for the buffer allocated. Each entry has
330 * a virtual and physical address and corresponds to PAGE_SIZE large
331 * buffer.
332 */
333 if (MapRegisterCount > 0)
334 {
335 PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry;
336
337 CurrentEntry = AdapterObject->MapRegisterBase + AdapterObject->NumberOfMapRegisters;
338 do
339 {
340 /*
341 * Leave one entry free for every non-contiguous memory region
342 * in the map register bitmap. This ensures that we can search
343 * using RtlFindClearBits for contiguous map register regions.
344 *
345 * Also for non-EISA DMA leave one free entry for every 64Kb
346 * break, because the DMA controller can handle only coniguous
347 * 64Kb regions.
348 */
349 if (CurrentEntry != AdapterObject->MapRegisterBase)
350 {
351 PreviousEntry = CurrentEntry - 1;
352 if ((PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE) == PhysicalAddress.LowPart)
353 {
354 if (!HalpEisaDma)
355 {
356 if ((PreviousEntry->PhysicalAddress.LowPart ^ PhysicalAddress.LowPart) & 0xFFFF0000)
357 {
358 CurrentEntry++;
359 AdapterObject->NumberOfMapRegisters++;
360 }
361 }
362 }
363 else
364 {
365 CurrentEntry++;
366 AdapterObject->NumberOfMapRegisters++;
367 }
368 }
369
370 RtlClearBit(AdapterObject->MapRegisters,
371 (ULONG)(CurrentEntry - AdapterObject->MapRegisterBase));
372 CurrentEntry->VirtualAddress = VirtualAddress;
373 CurrentEntry->PhysicalAddress = PhysicalAddress;
374
377
378 CurrentEntry++;
379 AdapterObject->NumberOfMapRegisters++;
381 } while (MapRegisterCount);
382 }
383
384 KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
385
386 return TRUE;
387}
#define RtlClearBit
Definition: dbgbitmap.h:330
#define DPRINT
Definition: sndvol32.h:73
PHYSICAL_ADDRESS PhysicalAddress
Definition: haldma.h:315
PVOID VirtualAddress
Definition: haldma.h:314
_In_ WDFDMATRANSACTION _Out_opt_ ULONG * MapRegisterCount
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1098

Referenced by HalpDmaAllocateMasterAdapter(), and HalpGrowMapBufferWorker().

◆ HalpGrowMapBufferWorker()

VOID NTAPI HalpGrowMapBufferWorker ( IN PVOID  DeferredContext)

Definition at line 1417 of file dma.c.

1418{
1420 KIRQL OldIrql;
1421 BOOLEAN Succeeded;
1422
1423 /*
1424 * Try to allocate new map registers for the adapter.
1425 *
1426 * NOTE: The NT implementation actually tries to allocate more map
1427 * registers than needed as an optimization.
1428 */
1430 Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter,
1431 WorkItem->NumberOfMapRegisters << PAGE_SHIFT);
1432 KeSetEvent(&HalpDmaLock, 0, 0);
1433
1434 if (Succeeded)
1435 {
1436 /*
1437 * Flush the adapter queue now that new map registers are ready. The
1438 * easiest way to do that is to call IoFreeMapRegisters to not free
1439 * any registers. Note that we use the magic (PVOID)2 map register
1440 * base to bypass the parameter checking.
1441 */
1443 IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
1445 }
1446
1448}
VOID FASTCALL KfLowerIrql(IN KIRQL NewIrql)
Definition: pic.c:232
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
VOID NTAPI IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject, IN PVOID MapRegisterBase, IN ULONG NumberOfMapRegisters)
Definition: dma.c:1752
struct _GROW_WORK_ITEM * PGROW_WORK_ITEM
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:739

Referenced by HalAllocateAdapterChannel().

◆ HalpInitDma()

VOID HalpInitDma ( VOID  )

Definition at line 186 of file dma.c.

187{
188 /*
189 * Initialize the DMA Operation table
190 */
196
198 {
199 /*
200 * Check if Extended DMA is available. We're just going to do a random
201 * read and write.
202 */
203 WRITE_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)), 0x2A);
204 if (READ_PORT_UCHAR(UlongToPtr(FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2))) == 0x2A)
205 {
206 DPRINT1("Machine supports EISA DMA. Bus type: %lu\n", HalpBusType);
208 }
209 }
210
211 /*
212 * Intialize all the global variables and allocate master adapter with
213 * first map buffers.
214 */
219
220 /*
221 * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's
222 * used by IoGetDmaAdapter in the kernel.
223 */
225}
#define DPRINT1
Definition: precomp.h:8
ULONG HalpBusType
Definition: pcibus.c:18
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
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
PADAPTER_OBJECT NTAPI HalpDmaAllocateMasterAdapter(VOID)
Definition: dma.c:399
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:1931
PDMA_ADAPTER NTAPI HalpGetDmaAdapter(IN PVOID Context, IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
Definition: dma.c:853
#define MACHINE_TYPE_EISA
Definition: ketypes.h:108
@ NotificationEvent
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
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
PFREE_ADAPTER_CHANNEL FreeAdapterChannel
Definition: iotypes.h:2641
PALLOCATE_ADAPTER_CHANNEL AllocateAdapterChannel
Definition: iotypes.h:2639
PFLUSH_ADAPTER_BUFFERS FlushAdapterBuffers
Definition: iotypes.h:2640
PFREE_MAP_REGISTERS FreeMapRegisters
Definition: iotypes.h:2642
PMAP_TRANSFER MapTransfer
Definition: iotypes.h:2643
#define HalGetDmaAdapter
Definition: haltypes.h:312
VOID(NTAPI * PFREE_ADAPTER_CHANNEL)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2345
VOID(NTAPI * PFREE_MAP_REGISTERS)(_In_ PDMA_ADAPTER DmaAdapter, PVOID MapRegisterBase, ULONG NumberOfMapRegisters)
Definition: iotypes.h:2349
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:2355
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:2336
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:2328

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

993{
994 PSCATTER_GATHER_CONTEXT AdapterControlContext = Context;
995 PADAPTER_OBJECT AdapterObject = AdapterControlContext->AdapterObject;
996 PSCATTER_GATHER_LIST ScatterGatherList;
997 PSCATTER_GATHER_ELEMENT TempElements;
998 ULONG ElementCount = 0, RemainingLength = AdapterControlContext->Length;
999 PUCHAR CurrentVa = AdapterControlContext->CurrentVa;
1000
1001 /* Store the map register base for later in HalPutScatterGatherList */
1002 AdapterControlContext->MapRegisterBase = MapRegisterBase;
1003
1004 // FIXME: HACK Allocate TempElements from pool to minimize stack usage.
1005 // A more efficient algorithm should be found to avoid allocations during S/G I/O operations.
1007 sizeof(*TempElements) * MAX_SG_ELEMENTS,
1008 TAG_DMA);
1009 if (!TempElements)
1010 {
1011 DPRINT1("Scatter/gather list construction failed!\n");
1012 return DeallocateObject;
1013 }
1014
1015 while (RemainingLength > 0 && ElementCount < MAX_SG_ELEMENTS)
1016 {
1017 TempElements[ElementCount].Length = RemainingLength;
1018 TempElements[ElementCount].Reserved = 0;
1019 TempElements[ElementCount].Address = IoMapTransfer(AdapterObject,
1020 AdapterControlContext->Mdl,
1022 CurrentVa + (AdapterControlContext->Length - RemainingLength),
1023 &TempElements[ElementCount].Length,
1024 AdapterControlContext->WriteToDevice);
1025 if (TempElements[ElementCount].Length == 0)
1026 break;
1027
1028 DPRINT("Allocated one S/G element: 0x%I64u with length: 0x%x\n",
1029 TempElements[ElementCount].Address.QuadPart,
1030 TempElements[ElementCount].Length);
1031
1032 ASSERT(TempElements[ElementCount].Length <= RemainingLength);
1033 RemainingLength -= TempElements[ElementCount].Length;
1034 ElementCount++;
1035 }
1036
1037 if (RemainingLength > 0)
1038 {
1039 DPRINT1("Scatter/gather list construction failed!\n");
1040 ExFreePoolWithTag(TempElements, TAG_DMA);
1041 return DeallocateObject;
1042 }
1043
1044 ScatterGatherList = ExAllocatePoolWithTag(NonPagedPool,
1045 sizeof(SCATTER_GATHER_LIST) + sizeof(SCATTER_GATHER_ELEMENT) * ElementCount,
1046 TAG_DMA);
1047 ASSERT(ScatterGatherList);
1048
1049 ScatterGatherList->NumberOfElements = ElementCount;
1050 ScatterGatherList->Reserved = (ULONG_PTR)AdapterControlContext;
1051 RtlCopyMemory(ScatterGatherList->Elements,
1052 TempElements,
1053 sizeof(SCATTER_GATHER_ELEMENT) * ElementCount);
1054
1055 ExFreePoolWithTag(TempElements, TAG_DMA);
1056
1057 DPRINT("Initiating S/G DMA with %d element(s)\n", ElementCount);
1058
1059 AdapterControlContext->AdapterListControlRoutine(DeviceObject,
1060 Irp,
1061 ScatterGatherList,
1062 AdapterControlContext->AdapterListControlContext);
1063
1065}
#define ExAllocatePoolUninitialized
_In_ PIRP Irp
Definition: csq.h:116
#define MAX_SG_ELEMENTS
Definition: dma.c:81
static WCHAR Address[46]
Definition: ping.c:68
PVOID MapRegisterBase
Definition: dma.c:980
PHYSICAL_ADDRESS Address
Definition: iotypes.h:2175
struct _SCATTER_GATHER_LIST SCATTER_GATHER_LIST
Definition: iotypes.h:2206
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2206

Referenced by HalBuildScatterGatherList().

◆ HalPutDmaAdapter()

VOID NTAPI HalPutDmaAdapter ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 870 of file dma.c.

871{
873 if (AdapterObject->ChannelNumber == 0xFF)
874 {
876 RemoveEntryList(&AdapterObject->AdapterList);
878 }
879
880 ObDereferenceObject(AdapterObject);
881}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986

◆ HalPutScatterGatherList()

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

Definition at line 1138 of file dma.c.

1141{
1142 PSCATTER_GATHER_CONTEXT AdapterControlContext = (PSCATTER_GATHER_CONTEXT)ScatterGather->Reserved;
1143 ULONG i;
1144
1145 for (i = 0; i < ScatterGather->NumberOfElements; i++)
1146 {
1147 IoFlushAdapterBuffers(AdapterObject,
1148 AdapterControlContext->Mdl,
1149 AdapterControlContext->MapRegisterBase,
1150 AdapterControlContext->CurrentVa,
1151 ScatterGather->Elements[i].Length,
1152 AdapterControlContext->WriteToDevice);
1153 AdapterControlContext->CurrentVa += ScatterGather->Elements[i].Length;
1154 }
1155
1156 IoFreeMapRegisters(AdapterObject,
1157 AdapterControlContext->MapRegisterBase,
1158 AdapterControlContext->MapRegisterCount);
1159
1160
1162
1163 /* If this is our buffer, release it */
1164 if (!AdapterControlContext->UsingUserBuffer)
1165 ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
1166
1167 DPRINT("S/G DMA has finished!\n");
1168}
for(i=0;i< ARRAY_SIZE(offsets);i++)
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:2377

◆ HalReadDmaCounter()

ULONG NTAPI HalReadDmaCounter ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 1345 of file dma.c.

1346{
1347 KIRQL OldIrql;
1348 ULONG Count, OldCount;
1349
1350 ASSERT(!AdapterObject->MasterDevice);
1351
1352 /*
1353 * Acquire the master adapter lock since we're going to mess with the
1354 * system DMA controller registers and we really don't want anyone
1355 * to do the same at the same time.
1356 */
1357 KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
1358
1359 /* Send the request to the specific controller. */
1360 if (AdapterObject->AdapterNumber == 1)
1361 {
1362 PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1363
1364 Count = 0xffff00;
1365 do
1366 {
1367 OldCount = Count;
1368
1369 /* Send Reset */
1370 WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
1371
1372 /* Read Count */
1373 Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1374 [AdapterObject->ChannelNumber].DmaBaseCount);
1375 Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
1376 [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1377 } while (0xffff00 & (OldCount ^ Count));
1378 }
1379 else
1380 {
1381 PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1382
1383 Count = 0xffff00;
1384 do
1385 {
1386 OldCount = Count;
1387
1388 /* Send Reset */
1389 WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
1390
1391 /* Read Count */
1392 Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1393 [AdapterObject->ChannelNumber].DmaBaseCount);
1394 Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
1395 [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
1396 } while (0xffff00 & (OldCount ^ Count));
1397 }
1398
1399 KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
1400
1401 Count++;
1402 Count &= 0xffff;
1403 if (AdapterObject->Width16Bits) Count *= 2;
1404
1405 return Count;
1406}
int Count
Definition: noreturn.cpp:7
UCHAR DmaBaseCount
Definition: haldma.h:184
UCHAR ClearBytePointer
Definition: haldma.h:202
DMA1_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:197
UCHAR DmaBaseCount
Definition: haldma.h:191
UCHAR ClearBytePointer
Definition: haldma.h:219
DMA2_ADDRESS_COUNT DmaAddressCount[4]
Definition: haldma.h:210

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

1937{
1938 BOOLEAN SlaveDma = FALSE;
1939 PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1942 PPFN_NUMBER MdlPagesPtr;
1943
1944 /* Sanity checks */
1946 ASSERT(AdapterObject);
1947
1948 if (!AdapterObject->MasterDevice)
1949 {
1950 /* Mask out (disable) the DMA channel. */
1951 if (AdapterObject->AdapterNumber == 1)
1952 {
1953 PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
1954 WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
1955 AdapterObject->ChannelNumber | DMA_SETMASK);
1956 }
1957 else
1958 {
1959 PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
1960 WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
1961 AdapterObject->ChannelNumber | DMA_SETMASK);
1962 }
1963 SlaveDma = TRUE;
1964 }
1965
1966 /* This can happen if the device supports hardware scatter/gather. */
1967 if (MapRegisterBase == NULL) return TRUE;
1968
1969 RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1970
1971 if (!WriteToDevice)
1972 {
1974 {
1975 if (RealMapRegisterBase->Counter != MAXULONG)
1976 {
1977 if ((SlaveDma) && !(AdapterObject->IgnoreCount))
1978 {
1979 Length -= HalReadDmaCounter(AdapterObject);
1980 }
1981 }
1983 RealMapRegisterBase,
1984 CurrentVa,
1985 Length,
1986 FALSE);
1987 }
1988 else
1989 {
1990 MdlPagesPtr = MmGetMdlPfnArray(Mdl);
1991 MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
1992
1993 PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
1994 PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa);
1995
1998 {
2000 RealMapRegisterBase,
2001 CurrentVa,
2002 Length,
2003 FALSE);
2004 }
2005 }
2006 }
2007
2008 RealMapRegisterBase->Counter = 0;
2009
2010 return TRUE;
2011}
VOID NTAPI HalpCopyBufferMap(IN PMDL Mdl, IN PROS_MAP_REGISTER_ENTRY MapRegisterBase, IN PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice)
Definition: dma.c:1848
ULONG NTAPI HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:1345
#define DMA_SETMASK
Definition: haldma.h:174
#define ASSERT_IRQL_LESS_OR_EQUAL(x)
Definition: debug.h:251
ULONG * PPFN_NUMBER
Definition: ke.h:9
UCHAR SingleMask
Definition: haldma.h:200
UCHAR SingleMask
Definition: haldma.h:215
ULONG Counter
Definition: haldma.h:316
#define MmGetMdlPfnArray(_Mdl)

◆ IoFreeAdapterChannel()

VOID NTAPI IoFreeAdapterChannel ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 1639 of file dma.c.

1640{
1641 PADAPTER_OBJECT MasterAdapter;
1643 PWAIT_CONTEXT_BLOCK WaitContextBlock;
1645 ULONG Result;
1646 KIRQL OldIrql;
1647
1648 MasterAdapter = AdapterObject->MasterAdapter;
1649
1650 for (;;)
1651 {
1652 /*
1653 * To keep map registers, call here with AdapterObject->
1654 * NumberOfMapRegisters set to zero. This trick is used in
1655 * HalAllocateAdapterChannel for example.
1656 */
1657 if (AdapterObject->NumberOfMapRegisters)
1658 {
1659 IoFreeMapRegisters(AdapterObject,
1660 AdapterObject->MapRegisterBase,
1661 AdapterObject->NumberOfMapRegisters);
1662 }
1663
1664 DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
1665 if (!DeviceQueueEntry) break;
1666
1667 WaitContextBlock = CONTAINING_RECORD(DeviceQueueEntry,
1669 WaitQueueEntry);
1670
1671 AdapterObject->CurrentWcb = WaitContextBlock;
1672 AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters;
1673
1674 if ((WaitContextBlock->NumberOfMapRegisters) && (AdapterObject->MasterAdapter))
1675 {
1676 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1677
1678 if (IsListEmpty(&MasterAdapter->AdapterQueue))
1679 {
1680 Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1681 WaitContextBlock->NumberOfMapRegisters,
1682 0);
1683 if (Index != MAXULONG)
1684 {
1685 AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1686 if (!AdapterObject->ScatterGather)
1687 {
1688 AdapterObject->MapRegisterBase =(PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1689 }
1690 }
1691 }
1692
1693 if (Index == MAXULONG)
1694 {
1695 InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
1696 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1697 break;
1698 }
1699
1700 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1701 }
1702 else
1703 {
1704 AdapterObject->MapRegisterBase = NULL;
1705 AdapterObject->NumberOfMapRegisters = 0;
1706 }
1707
1708 /* Call the adapter control routine. */
1709 Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject,
1710 WaitContextBlock->CurrentIrp,
1711 AdapterObject->MapRegisterBase,
1712 WaitContextBlock->DeviceContext);
1713 switch (Result)
1714 {
1715 case KeepObject:
1716 /*
1717 * We're done until the caller manually calls IoFreeAdapterChannel
1718 * or IoFreeMapRegisters.
1719 */
1720 return;
1721
1723 /*
1724 * Hide the map registers so they aren't deallocated next time
1725 * around.
1726 */
1727 AdapterObject->NumberOfMapRegisters = 0;
1728 break;
1729
1730 default:
1731 break;
1732 }
1733 }
1734}
PKDEVICE_QUEUE_ENTRY NTAPI KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:153
Definition: ketypes.h:630
ULONG NumberOfMapRegisters
Definition: iotypes.h:221
PDRIVER_CONTROL DeviceRoutine
Definition: iotypes.h:219
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
@ KeepObject
Definition: iotypes.h:202
DRIVER_CONTROL * PDRIVER_CONTROL
Definition: iotypes.h:215
_Inout_ PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
Definition: kefuncs.h:327

◆ IoFreeMapRegisters()

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

Definition at line 1752 of file dma.c.

1755{
1756 PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
1757 PLIST_ENTRY ListEntry;
1758 KIRQL OldIrql;
1759 ULONG Index;
1760 ULONG Result;
1761
1763
1764 if (!(MasterAdapter) || !(MapRegisterBase)) return;
1765
1766 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1767
1768 if (NumberOfMapRegisters != 0)
1769 {
1770 PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
1771
1772 RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
1773 RtlClearBits(MasterAdapter->MapRegisters,
1774 (ULONG)(RealMapRegisterBase - MasterAdapter->MapRegisterBase),
1776 }
1777
1778 /*
1779 * Now that we freed few map registers it's time to look at the master
1780 * adapter queue and see if there is someone waiting for map registers.
1781 */
1782 while (!IsListEmpty(&MasterAdapter->AdapterQueue))
1783 {
1784 ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue);
1785 AdapterObject = CONTAINING_RECORD(ListEntry, struct _ADAPTER_OBJECT, AdapterQueue);
1786
1787 Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
1788 AdapterObject->NumberOfMapRegisters,
1789 0);
1790 if (Index == MAXULONG)
1791 {
1792 InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
1793 break;
1794 }
1795
1796 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1797
1798 AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
1799 if (!AdapterObject->ScatterGather)
1800 {
1801 AdapterObject->MapRegisterBase =
1802 (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
1803 }
1804
1805 Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(AdapterObject->CurrentWcb->DeviceObject,
1806 AdapterObject->CurrentWcb->CurrentIrp,
1807 AdapterObject->MapRegisterBase,
1808 AdapterObject->CurrentWcb->DeviceContext);
1809 switch (Result)
1810 {
1812 AdapterObject->NumberOfMapRegisters = 0;
1813 /* fall through */
1814
1815 case DeallocateObject:
1816 if (AdapterObject->NumberOfMapRegisters)
1817 {
1818 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1819 RtlClearBits(MasterAdapter->MapRegisters,
1820 (ULONG)(AdapterObject->MapRegisterBase -
1821 MasterAdapter->MapRegisterBase),
1822 AdapterObject->NumberOfMapRegisters);
1823 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1824 }
1825
1826 IoFreeAdapterChannel(AdapterObject);
1827 break;
1828
1829 default:
1830 break;
1831 }
1832
1833 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
1834 }
1835
1836 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
1837}
#define RtlClearBits
Definition: dbgbitmap.h:331
#define InsertHeadList(ListHead, Entry)
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
Definition: typedefs.h:120

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

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

Variable Documentation

◆ HalpDmaAdapterList

LIST_ENTRY HalpDmaAdapterList
static

Definition at line 86 of file dma.c.

Referenced by HalGetAdapter(), and HalpInitDma().

◆ HalpDmaAdapterListLock

KSPIN_LOCK HalpDmaAdapterListLock
static

Definition at line 85 of file dma.c.

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

◆ HalpDmaLock

KEVENT HalpDmaLock
static

Definition at line 84 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 HalAllocateCommonBuffer(IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PPHYSICAL_ADDRESS LogicalAddress, IN BOOLEAN CacheEnabled)
Definition: dma.c:46
NTSTATUS NTAPI HalBuildMdlFromScatterGatherList(IN PDMA_ADAPTER DmaAdapter, IN PSCATTER_GATHER_LIST ScatterGather, IN PMDL OriginalMdl, OUT PMDL *TargetMdl)
Definition: dma.c:1310
VOID NTAPI HalPutDmaAdapter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:870
ULONG NTAPI HalpDmaGetDmaAlignment(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:1331
VOID NTAPI HalPutScatterGatherList(IN PADAPTER_OBJECT AdapterObject, IN PSCATTER_GATHER_LIST ScatterGather, IN BOOLEAN WriteToDevice)
Definition: dma.c:1138
VOID NTAPI HalFreeCommonBuffer(IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress, IN BOOLEAN CacheEnabled)
Definition: dma.c:962
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:1097
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:2408
struct _DMA_OPERATIONS DMA_OPERATIONS
ULONG(NTAPI * PREAD_DMA_COUNTER)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2368
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:2421
PVOID(NTAPI * PALLOCATE_COMMON_BUFFER)(_In_ PDMA_ADAPTER DmaAdapter, _In_ ULONG Length, _Out_ PPHYSICAL_ADDRESS LogicalAddress, _In_ BOOLEAN CacheEnabled)
Definition: iotypes.h:2313
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:2382
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:2399
VOID(NTAPI * PPUT_SCATTER_GATHER_LIST)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PSCATTER_GATHER_LIST ScatterGather, _In_ BOOLEAN WriteToDevice)
Definition: iotypes.h:2393
VOID(NTAPI * PPUT_DMA_ADAPTER)(PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2309
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:2320
ULONG(NTAPI * PGET_DMA_ALIGNMENT)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2364

Definition at line 139 of file dma.c.

Referenced by HalpDmaAllocateChildAdapter(), and HalpInitDma().

◆ HalpEisaAdapter

PADAPTER_OBJECT HalpEisaAdapter[8]
static

Definition at line 87 of file dma.c.

Referenced by HalGetAdapter().

◆ HalpEisaDma

BOOLEAN HalpEisaDma
static

Definition at line 89 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),
}

Definition at line 94 of file dma.c.

Referenced by HalpDmaInitializeEisaAdapter().

◆ HalpMasterAdapter

PADAPTER_OBJECT HalpMasterAdapter
static

Definition at line 91 of file dma.c.

Referenced by HalpDmaAllocateChildAdapter(), and HalpInitDma().