ReactOS 0.4.15-dev-7918-g2a2556c
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;
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}
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:160
VOID NTAPI HalpGrowMapBufferWorker(IN PVOID DeferredContext)
Definition: dma.c:1402
VOID NTAPI IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:1624
struct _ROS_MAP_REGISTER_ENTRY * PROS_MAP_REGISTER_ENTRY
#define MAP_BASE_SW_SG
Definition: haldma.h:367
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
#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 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 :
943 if (VirtualAddress == NULL) return NULL;
944
945 *LogicalAddress = MmGetPhysicalAddress(VirtualAddress);
946
947 return VirtualAddress;
948}
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:235
_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 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}
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)

◆ 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{
1303}
#define UNIMPLEMENTED
Definition: debug.h:115
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239

◆ 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{
1229 PSCATTER_GATHER_CONTEXT ScatterGatherContext;
1230 BOOLEAN UsingUserBuffer;
1231
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 {
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}
unsigned char BOOLEAN
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:32
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:988
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:1461
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
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
PVOID AdapterListControlContext
Definition: dma.c:979
ULONG MapRegisterCount
Definition: dma.c:980
WAIT_CONTEXT_BLOCK Wcb
Definition: dma.c:982
PADAPTER_OBJECT AdapterObject
Definition: dma.c:974
BOOLEAN UsingUserBuffer
Definition: dma.c:973
BOOLEAN WriteToDevice
Definition: dma.c:981
PDRIVER_LIST_CONTROL AdapterListControlRoutine
Definition: dma.c:978
void * PVOID
Definition: typedefs.h:50
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_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 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
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 2307 of file dma.c.

2311{
2312 /* Function always returns true */
2313 return TRUE;
2314}

◆ 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}
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;
669
670 /* Validate parameters in device description */
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 {
688 }
689 else
690 {
692 }
693 }
694 else
695 {
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 {
833 {
834 ObDereferenceObject(AdapterObject);
835 return NULL;
836 }
837 }
838
839 return AdapterObject;
840}
@ 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:83
static KSPIN_LOCK HalpDmaAdapterListLock
Definition: dma.c:84
PADAPTER_OBJECT NTAPI HalpDmaAllocateChildAdapter(IN ULONG NumberOfMapRegisters, IN PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:455
static PADAPTER_OBJECT HalpEisaAdapter[8]
Definition: dma.c:86
static LIST_ENTRY HalpDmaAdapterList
Definition: dma.c:85
BOOLEAN NTAPI HalpDmaInitializeEisaAdapter(IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_DESCRIPTION DeviceDescription)
Definition: dma.c:514
@ Eisa
Definition: hwresource.cpp:139
@ PCIBus
Definition: hwresource.cpp:142
@ Isa
Definition: hwresource.cpp:138
#define KernelMode
Definition: asm.h:34
#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:415
#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 1082 of file dma.c.

1090{
1091 return HalBuildScatterGatherList(AdapterObject,
1093 Mdl,
1094 CurrentVa,
1095 Length,
1097 Context,
1099 NULL,
1100 0);
1101}
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;
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 {
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;
1880 }
1881}
#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:731
@ HighPagePriority
Definition: imports.h:57
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
#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 455 of file dma.c.

457{
458 PADAPTER_OBJECT AdapterObject;
462
464 NULL,
466 NULL,
467 NULL);
468
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
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: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:90
static DMA_OPERATIONS HalpDmaOperations
Definition: dma.c:138
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_PERMANENT
Definition: winternl.h:226
#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
struct _DMA_OPERATIONS * DmaOperations
Definition: iotypes.h:2295
USHORT Size
Definition: iotypes.h:2294
USHORT Version
Definition: iotypes.h:2293
#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 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
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 *
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}
#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:158
BOOLEAN NTAPI HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject, IN ULONG SizeOfMapBuffers)
Definition: dma.c:271
struct _ADAPTER_OBJECT ADAPTER_OBJECT
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
Definition: haldma.h:313
uint32_t * PULONG
Definition: typedefs.h:59
struct _RTL_BITMAP RTL_BITMAP
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

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
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}
#define UlongToPtr(u)
Definition: config.h:106
static BOOLEAN HalpEisaDma
Definition: dma.c:88
static const ULONG_PTR HalpEisaPortPage[8]
Definition: dma.c:93
#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
#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
unsigned char UCHAR
Definition: xmlstorage.h:181

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}

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

273{
278 PHYSICAL_ADDRESS BoundryAddressMultiple;
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,
308 {
313 BoundryAddressMultiple,
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}
VOID NTAPI RtlClearBit(_In_ PRTL_BITMAP BitMapHeader, _In_ BITMAP_INDEX BitNumber)
Definition: bitmap.c:294
#define DPRINT
Definition: sndvol32.h:71
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 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}
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:1737
struct _GROW_WORK_ITEM * PGROW_WORK_ITEM
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687

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);
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 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:398
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:1916
PDMA_ADAPTER NTAPI HalpGetDmaAdapter(IN PVOID Context, IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
Definition: dma.c:852
#define MACHINE_TYPE_EISA
Definition: ketypes.h:114
@ 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:2639
PALLOCATE_ADAPTER_CHANNEL AllocateAdapterChannel
Definition: iotypes.h:2637
PFLUSH_ADAPTER_BUFFERS FlushAdapterBuffers
Definition: iotypes.h:2638
PFREE_MAP_REGISTERS FreeMapRegisters
Definition: iotypes.h:2640
PMAP_TRANSFER MapTransfer
Definition: iotypes.h:2641
#define HalGetDmaAdapter
Definition: haltypes.h:302
VOID(NTAPI * PFREE_ADAPTER_CHANNEL)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2343
VOID(NTAPI * PFREE_MAP_REGISTERS)(_In_ PDMA_ADAPTER DmaAdapter, PVOID MapRegisterBase, ULONG NumberOfMapRegisters)
Definition: iotypes.h:2347
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
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
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

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}
_In_ PIRP Irp
Definition: csq.h:116
#define MAX_SG_ELEMENTS
Definition: dma.c:80
static WCHAR Address[46]
Definition: ping.c:68
PVOID MapRegisterBase
Definition: dma.c:979
PHYSICAL_ADDRESS Address
Definition: iotypes.h:2173
struct _SCATTER_GATHER_LIST SCATTER_GATHER_LIST
Definition: iotypes.h:2204
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2204

Referenced by HalBuildScatterGatherList().

◆ HalPutDmaAdapter()

VOID NTAPI HalPutDmaAdapter ( IN PADAPTER_OBJECT  AdapterObject)

Definition at line 869 of file dma.c.

870{
872 if (AdapterObject->ChannelNumber == 0xFF)
873 {
875 RemoveEntryList(&AdapterObject->AdapterList);
877 }
878
879 ObDereferenceObject(AdapterObject);
880}
#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 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}
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
#define for
Definition: utility.h:88
_In_ struct _IRP _In_ struct _SCATTER_GATHER_LIST * ScatterGather
Definition: iotypes.h:2375

◆ 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}
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 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}
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
ULONG NTAPI HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:1330
#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 1624 of file dma.c.

1625{
1626 PADAPTER_OBJECT MasterAdapter;
1628 PWAIT_CONTEXT_BLOCK WaitContextBlock;
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}
PKDEVICE_QUEUE_ENTRY NTAPI KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:153
Definition: ketypes.h:578
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 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 InsertHeadList(ListHead, Entry)
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
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 2031 of file dma.c.

2037{
2038 PPFN_NUMBER MdlPagesPtr;
2039 PFN_NUMBER MdlPage1, MdlPage2;
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,
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,
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,
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}
#define WRITE_TRANSFER
Definition: haldma.h:166
#define READ_TRANSFER
Definition: haldma.h:165
ULONG PFN_NUMBER
Definition: ke.h:9
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::@2295 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 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 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:1295
VOID NTAPI HalPutDmaAdapter(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:869
ULONG NTAPI HalpDmaGetDmaAlignment(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:1316
VOID NTAPI HalPutScatterGatherList(IN PADAPTER_OBJECT AdapterObject, IN PSCATTER_GATHER_LIST ScatterGather, IN BOOLEAN WriteToDevice)
Definition: dma.c:1123
VOID NTAPI HalFreeCommonBuffer(IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress, IN BOOLEAN CacheEnabled)
Definition: dma.c:961
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 * 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
struct _DMA_OPERATIONS DMA_OPERATIONS
ULONG(NTAPI * PREAD_DMA_COUNTER)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2366
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
PVOID(NTAPI * PALLOCATE_COMMON_BUFFER)(_In_ PDMA_ADAPTER DmaAdapter, _In_ ULONG Length, _Out_ PPHYSICAL_ADDRESS LogicalAddress, _In_ BOOLEAN CacheEnabled)
Definition: iotypes.h:2311
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 * 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
VOID(NTAPI * PPUT_SCATTER_GATHER_LIST)(_In_ PDMA_ADAPTER DmaAdapter, _In_ PSCATTER_GATHER_LIST ScatterGather, _In_ BOOLEAN WriteToDevice)
Definition: iotypes.h:2391
VOID(NTAPI * PPUT_DMA_ADAPTER)(PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2307
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
ULONG(NTAPI * PGET_DMA_ALIGNMENT)(_In_ PDMA_ADAPTER DmaAdapter)
Definition: iotypes.h:2362

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),
}

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