PURPOSE
Enables Contiguous Buffer or Scatter/Gather DMA.
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 98/Me/2000/XP/Server 2003/Vista 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 |
|---|---|---|
| HANDLE | Input | |
| WD_DMA* | ||
| DWORD | Output | |
| PVOID | Input/Output | |
| KPTR | Output | |
| DWORD | Input | |
| DWORD | Input | |
| DWORD | Input/Output | |
| DWORD | Input | |
| WD_DMA_PAGE[WD_DMA_PAGES] | ||
| DMA_ADDR | Output | |
| 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: |
| DMA buffer handle, which should be passed to WD_DMAUnlock() [2.14] when unlocking the DMA buffer, or 0 if the DMA lock failed | |
| Virtual user-mode mapped DMA buffer address. Input in the case of Scatter/Gather and output in the case of contiguous buffer DMA. | |
| Kernel-mode mapped DMA buffer address. Relevant only for Contiguous Buffer DMA (dwOptions | DMA_KERNEL_BUFFER_ALLOC) and for Scatter/Gather DMA on Windows 98/Me/2000/XP/Server 2003/Vista. | |
| The size of the DMA buffer, in bytes | |
| DMA options bit-mask, which can consist of a combination of
any of the following flags: The default behavior (when this flag is not set) is to allocate a Scatter/Gather DMA buffer. This flag is applicable only to Contiguous Buffer DMA, i.e. only when the DMA_KERNEL_BUFFER_ALLOC flag is also set. This flag is applicable only to Scatter/Gather DMA (i.e. when the DMA_KERNEL_BUFFER_ALLOC flag is not set). This flag is applicable only in cases where the DMA_KERNEL_BUFFER_ALLOC flag is applicable - see above. |
|
| 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 2.13 . |
|
| 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. |
|
| Array of DMA page structures: | |
| Pointer to the physical address of the beginning of the page | |
| Page size, in bytes |
RETURN VALUE
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [A].
REMARKS
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 98/Me/2000/XP/Server 2003/Vista, 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.
EXAMPLES
The following code demonstrates Scatter/Gather DMA allocation:
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. */
}