• 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 7/Vista/Server 2008/Server 2003/XP/2000 the function also returns a kernel-mode mapping of the buffer.
DWORD WD_DMALock(
HANDLE hWD,
WD_DMA *pDma);
| 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 |
| 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.14] 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. |
| • pKernelAddr |
Kernel-mode mapped DMA buffer address. Relevant only for Contiguous
Buffer DMA (dwOptions | DMA_KERNEL_BUFFER_ALLOC) and for
Scatter/Gather DMA on Windows 7/Vista/Server 2008/Server 2003/XP/2000.
|
| • dwBytes | The size of the DMA buffer, in bytes |
| • dwOptions |
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.
|
| • dwOptions (continued) |
• 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, if supported by the target platform. This flag is
supported on Windows% 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.8].
This field can also be set to 0 in order to lock a kernel memory buffer without association to a specific device. |
| • Page | Array of DMA page structures: |
| * pPhysicalAddr | Pointer to the physical address of the beginning of the page |
| * dwBytes | Page size, in bytes |
WD_STATUS_SUCCESS(0) on success, or
an appropriate error code otherwise [A].
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.11] /
WD_MultiTransfer [2.12],
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 7/Vista/Server 2008/Server 2003/XP/2000, 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.8] 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.dwTransAddr
field.
DMA_ALLOW_CACHE flag in the DMA options bitmask parameter
(pDma->dwOptions).
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.
WD_DMA dma;
DWORD dwStatus;
PVOID pBuffer = malloc(20000);
BZERO(dma);
dma.dwBytes = 20000;
dma.pUserAddr = pBuffer;
dma.dwOptions = fIsRead ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
/* Initialization of dma.hCard, value obtained from WD_CardRegister call: */
dma.hCard = cardReg.hCard;
dwStatus = WD_DMALock(hWD, &dma);
if (dwStatus)
{
printf("Could not lock down buffer\n");
}
else
{
/* On successful return dma.Page has the list of
physical addresses.
To access the memory from your user mode
application, use dma.pUserAddr. */
}
• The following code demonstrates contiguous kernel buffer DMA
allocation:
WD_DMA dma;
DWORD dwStatus;
BZERO(dma);
dma.dwBytes = 20 * 4096; /* 20 pages */
dma.dwOptions = DMA_KERNEL_BUFFER_ALLOC |
( fIsRead ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
/* Initialization of dma.hCard, value obtained from WD_CardRegister call: */
dma.hCard = cardReg.hCard;
dwStatus = WD_DMALock(hWD, &dma);
if (dwStatus)
{
printf("Failed allocating kernel buffer for DMA\n");
}
else
{
/* On return dma.pUserAddr holds the user mode virtual
mapping of the allocated memory and dma.pKernelAddr
holds the kernel mapping of the physical memory.
dma.Page[0].pPhysicalAddr points to the allocated
physical address. */
}