2.11. WD_DMALock()

For contiguous-buffer DMA, the function allocates a DMA buffer and returns mappings
of the allocated buffer to physical address space and to user-mode and kernel
virtual address spaces.

For Scatter/﻿Gather DMA, the function receives the address of a data buffer allocated in
the user-mode, locks it for DMA, and returns the corresponding physical
mappings of the locked DMA pages. On Windows the function also returns a
kernel-mode mapping of the buffer.

Prototype

DWORD WD_DMALock(
HANDLE hWD,
WD_DMA *pDma);

Parameters

Name

Type

Input/Output

hWD

HANDLE

Input

pDma

WD_DMA*

• hDma

DWORD

Output

• pUserAddr

PVOID

Input/Output

• pKernelAddr

KPTR

Output

• dwBytes

DWORD

Input

• dwOptions

DWORD

Input

• dwPages

DWORD

Input/Output

• hCard

DWORD

Input

• Page

WD_DMA_PAGE[WD_DMA_PAGES]

* pPhysicalAddr

DMA_ADDR

Output

* dwBytes

DWORD

Output

Description

Name

Description

hWD

Handle to WinDriver's kernel-mode driver as
received from WD_Open() [5.2]

pDma

Pointer to a DMA information structure:

• hDma

DMA buffer handle, which should be passed to
WD_DMAUnlock() [2.12] when
unlocking the DMA buffer, or 0 if the DMA lock failed

• pUserAddr

Virtual user-mode mapped DMA buffer address. Input in the case of Scatter/﻿Gather
and output in the case of contiguous buffer DMA.

DMA options bit-mask, which can consist of a combination of any of the
following flags:
• DMA_FROM_DEVICE: Synchronize the DMA buffer for
transfers from the device to memory.
• DMA_TO_DEVICE: Synchronize the DMA buffer for
transfers from memory to the device.
• DMA_TO_FROM_DEVICE: Synchronize the DMA buffer for
transfers in both directions — i.e., from the device to memory and
from memory to the device (<=> DMA_FROM_DEVICE |
DMA_TO_DEVICE).
• DMA_KERNEL_BUFFER_ALLOC: Allocate a contiguous DMA
buffer in the physical memory.
The default behavior (when this flag is not set) is to allocate a
Scatter/﻿Gather DMA buffer.
• DMA_KBUF_BELOW_16M: Allocate the physical DMA buffer
within the first 16MB of the main memory.
This flag is applicable only to contiguous-buffer DMA, i.e., only when the
DMA_KERNEL_BUFFER_ALLOC flag is also set.
• DMA_LARGE_BUFFER: Enable locking of a large DMA
buffer — dwBytes > 1MB.
This flag is applicable only to Scatter/﻿Gather DMA (i.e., when the
DMA_KERNEL_BUFFER_ALLOC flag is not set).
• DMA_ALLOW_CACHE: Allow caching of the DMA buffer.
• DMA_KERNEL_ONLY_MAP: Do not map the allocated DMA
buffer to the user mode (i.e., map it to kernel-mode only).
This flag is applicable only in cases where the
DMA_KERNEL_BUFFER_ALLOC flag is applicable — see
above.
• DMA_ALLOW_64BIT_ADDRESS: Allow allocation of 64-﻿bit
DMA addresses. This flag is supported on Windows and and Linux.

• dwPages

The number of pages allocated for the DMA buffer.
For contiguous-buffer DMA this field is always set to 1.
For a large (> 1MB) Scatter/﻿Gather DMA buffer
(dwOptions | DMA_LARGE_BUFFER) this
field is used both as an input and an output parameter (otherwise only
output) — see
remark below for
details.

• hCard

Handle to a card for which the DMA buffer is locked, as received from
WD_CardRegister() [2.6].

WinDriver supports both Scatter/﻿Gather and contiguous-buffer DMA on Windows
and Linux.
On Linux, Scatter/﻿Gather DMA is only supported for 2.4 kernels and above (since the
2.2 Linux kernels require a patch to support this type of DMA).

You should NOT use the physical memory address returned by the function
(dma.Page[i].pPhysicalAddr) directly in order to access the
DMA buffer from your driver.

To access the memory directly from a user-mode process, use the user-mode
virtual mapping of the DMA buffer — dma.pUserAddr.

To access the memory in the kernel, either directly from within a Kernel
PlugIn driver (see the WinDriver PCI Manual) or when calling
WD_Transfer() [2.9] / WD_MultiTransfer() [2.10], use the kernel
mapping of the DMA buffer. For contiguous-buffer DMA
(dma.dwOptions | DMA_KERNEL_BUFFER_ALLOC)
and for Scatter/﻿Gather DMA on Windows, this mapping is returned by
WD_DMALock() within the dma.pKernelAddr field.
For Scatter/﻿Gather DMA on other platforms, you can acquire a kernel mapping of the
buffer by calling WD_CardRegister() [2.6] with a card structure that
contains a memory item defined with the physical DMA buffer address
returned from WD_DMALock()
(dma.Page[i].pPhysicalAddr).
WD_CardRegister() will return a kernel mapping of the physical
buffer within the
pCardReg->Card.Item[i].I.Mem.pTransAddr
field.

On Windows x86 and x86_64 platforms, you should normally set the
DMA_ALLOW_CACHE flag in the DMA options bitmask parameter
(pDma->dwOptions).

If the device supports 64-﻿bit DMA addresses, it is recommended to set the
DMA_ALLOW_64BIT_ADDRESS flag in
pDma->dwOptions.
Otherwise, when the physical memory on the target platform is larger than
4GB, the operating system may only allow allocation of relatively small
32-bit DMA buffers (such as 1MB buffers, or even smaller).

When using the DMA_LARGE_BUFFER flag, dwPages is
an input/output parameter. As input to WD_DMALock(),
dwPages should be set to the maximum number of pages that can
be used for the DMA buffer (normally this would be the number of elements
in the dma.Page array). As an output value of
WD_DMALock(), dwPages holds the number of actual
physical blocks allocated for the DMA buffer. The returned
dwPages may be smaller than the input value because adjacent
pages are returned as one block.