Contents
DmaInfo
The structure describing the DMA buffer is declared in the io/io_dma.h
file.
typedef struct {
/** DMA flags (attributes). */
DmaAttr flags;
/** Minimum order of DMA blocks in the buffer. */
rtl_size_t orderMin;
/** DMA buffer size. */
rtl_size_t size;
/** Number of DMA blocks (less than or equal to DMA_FRAMES_COUNT_MAX).
* It may be equal to 0 if a DMA buffer is not available for the device. */
rtl_size_t count;
/** Array of DMA block descriptors. */
union DmaFrameDescriptor {
struct {
/** Order of the DMA block. The number of pages in a block is equal to two
* to the power of the specified order. */
DmaAddr order: DMA_FRAME_ORDER_BITS;
/** Physical or IOMMU address of the DMA block. */
DmaAddr frame: DMA_FRAME_BASE_BITS;
};
/** DMA block descriptor */
DmaAddr raw;
} descriptors[1];
} DmaInfo;
DMA flags
DMA flags (attributes) are declared in the io/io_dma.h
file.
- DMA_DIR_TO_DEVICE allows transactions from the main memory to the device memory.
- DMA_DIR_FROM_DEVICE allows transactions from the device memory to the main memory.
- DMA_DIR_BIDIR allows transactions from the main memory to the device memory, and vice versa.
- DMA_ZONE_DMA32 allows the use of only the first 4 GB of memory for the buffer.
- DMA_ATTR_WRITE_BACK, DMA_ATTR_WRITE_THROUGH, DMA_ATTR_CACHE_DISABLE, and DMA_ATTR_WRITE_COMBINE are for managing the cache of memory pages.
KnIoDmaBegin()
This function is declared in the coresrv/io/dma.h
file.
Retcode KnIoDmaBegin(Handle rid, Handle *handle);
Allows the device to access the DMA buffer with the handle rid
.
Output parameter handle
contains the handle of this permission.
If successful, the function returns rcOk.
For a usage example, see KnIoDmaCreate().
To prevent a device from accessing the DMA buffer, you need to call the KnIoClose()
function while passing the specified handle
of the permission in this function.
KnIoDmaCreate()
This function is declared in the coresrv/io/dma.h
file.
Retcode KnIoDmaCreate(rtl_uint32_t order, rtl_size_t size, DmaAttr flags,
Handle *outRid);
This function registers and allocates a physical DMA buffer.
Input parameters:
order
is the minimum permissible order of DMA block allocation; the actual order of each block in the DMA buffer is chosen by the kernel (but will not be less than the specified order) and is indicated in the block handle; the order of a block determines the number of pages in it. For example, a block with an order of N consists of 2^N pages.size
refers to the size of the DMA buffer, in bytes (must be a multiple of the page size); the sum of all sizes of allocated DMA blocks will be no less than the specifiedsize
.flags
refers to DMA flags.
Output parameter outRid
contains the handle of the allocated DMA buffer.
If successful, the function returns rcOk.
If a DMA buffer is no longer being used, it must be freed by using the KnIoClose()
function.
Example
Retcode RegisterDmaMem(rtl_size_t size,
DmaAttr attr,
Handle *handle,
Handle *dmaHandle,
Handle *mappingHandle,
void **addr)
{
Retcode ret;
*handle = INVALID_HANDLE;
*dmaHandle = INVALID_HANDLE;
*mappingHandle = INVALID_HANDLE;
ret = KnIoDmaCreate(rtl_roundup_order(size >> PAGE_SHIFT),
size,
attr,
handle);
if (ret == rcOk) {
ret = KnIoDmaBegin(*handle, dmaHandle);
}
if (ret == rcOk) {
ret = KnIoDmaMap(*handle,
0,
size,
RTL_NULL,
VMM_FLAG_READ | VMM_FLAG_WRITE,
addr,
mappingHandle);
}
if (ret != rcOk) {
if (*mappingHandle != INVALID_HANDLE)
KnHandleClose(*mappingHandle);
if (*dmaHandle != INVALID_HANDLE)
KnHandleClose(*dmaHandle);
if (*handle != INVALID_HANDLE)
KnHandleClose(*handle);
}
return ret;
}
KnIoDmaGetInfo()
This function is declared in the coresrv/io/dma.h
file.
Retcode KnIoDmaGetInfo(Handle rid, DmaInfo **outInfo);
This function gets information about the DMA buffer with the handle rid
.
Output parameter outInfo
contains information about the DMA buffer.
If successful, the function returns rcOk.
In contrast to KnIoDmaGetPhysInfo()
, the outInfo
parameter contains IOMMU addresses of DMA blocks instead of physical addresses.
KnIoDmaGetPhysInfo()
This function is declared in the coresrv/io/dma.h
file.
Retcode KnIoDmaGetPhysInfo(Handle rid, DmaInfo **outInfo);
This function gets information about the DMA buffer with the handle rid
.
Output parameter outInfo
contains information about the DMA buffer.
If successful, the function returns rcOk.
In contrast to KnIoDmaGetInfo()
, the outInfo
parameter contains physical addresses of DMA blocks instead of IOMMU addresses.
KnIoDmaMap()
This function is declared in the coresrv/io/dma.h
file.
Retcode KnIoDmaMap(Handle rid, rtl_size_t offset, rtl_size_t length, void *hint,
int vmflags, void **addr, Handle *handle);
This function maps a DMA buffer area to the address space of a process.
Input parameters:
rid
is the handle of the DMA buffer allocated usingKnIoDmaCreate()
.offset
refers to the page-aligned offset of the start of the area from the start of the buffer, indicated in bytes.length
refers to the size of the area; it must be a multiple of the page size and must not exceed <buffer size -offset
>.hint
is the virtual address of the start of mapping; if it is equal to 0, the address is selected by the kernel.vmflags
refers to allocation flags.
In the vmflags
parameter, you can use the following allocation flags (vmm/flags.h
):
- VMM_FLAG_READ and VMM_FLAG_WRITE are memory protection attributes.
- VMM_FLAG_LOW_GUARD and VMM_FLAG_HIGH_GUARD add a protective page before and after the allocated memory, respectively.
Permissible combinations of memory protection attributes:
- VMM_FLAG_READ allows reading page contents.
- VMM_FLAG_WRITE allows modification of page contents.
- VMM_FLAG_READ | VMM_FLAG_WRITE allows reading and modifying page contents.
Output parameters:
addr
is the pointer to the virtual address of the start of the mapped area.handle
refers to the handle of the created mapping.
If successful, the function returns rcOk.
For a usage example, see KnIoDmaCreate().
To delete a created mapping, you must call the KnIoClose()
function and pass the specified mapping handle
in this function.