Содержание
DmaInfo
Структура, описывающая DMA-буфер, объявлена в файле io/io_dma.h
.
typedef struct {
/** DMA-флаги (атрибуты). */
DmaAttr flags;
/** Минимальный порядок DMA-блоков в буфере. */
rtl_size_t orderMin;
/** Размер DMA-буфера. */
rtl_size_t size;
/** Число DMA-блоков (меньше или равно DMA_FRAMES_COUNT_MAX).
* Может быть равно 0, если DMA-буфер недоступен для устройства. */
rtl_size_t count;
/** Массив описателей DMA-блоков. */
union DmaFrameDescriptor {
struct {
/** Порядок (order) DMA-блока. Число страниц в блоке равно двум
* в степени order. */
DmaAddr order: DMA_FRAME_ORDER_BITS;
/** Физический или IOMMU-адрес DMA-блока. */
DmaAddr frame: DMA_FRAME_BASE_BITS;
};
/** Описатель DMA-блока */
DmaAddr raw;
} descriptors[1];
} DmaInfo;
DMA-флаги
DMA-флаги (атрибуты) объявлены в файле io/io_dma.h
.
- DMA_DIR_TO_DEVICE – разрешены транзакции из основной памяти в память устройства;
- DMA_DIR_FROM_DEVICE – разрешены транзакции из памяти устройства в основную память;
- DMA_DIR_BIDIR – разрешены транзакции из основной памяти в память устройства и наоборот;
- DMA_ZONE_DMA32 – под буфер разрешено использовать только первые 4 Гб памяти;
- DMA_ATTR_WRITE_BACK, DMA_ATTR_WRITE_THROUGH, DMA_ATTR_CACHE_DISABLE, DMA_ATTR_WRITE_COMBINE – управление кэшированием страниц памяти.
KnIoDmaBegin()
Функция объявлена в файле coresrv/io/dma.h
.
Retcode KnIoDmaBegin(Handle rid, Handle *handle);
Функция разрешает устройству доступ к DMA-буферу с дескриптором rid
.
Выходной параметр handle
содержит дескриптор данного разрешения.
В случае успеха функция возвращает rcOk.
Пример использования – см. KnIoDmaCreate().
Чтобы запретить устройству доступ к DMA-буферу, необходимо вызвать функцию KnIoClose()
, передав в нее дескриптор разрешения handle
.
KnIoDmaCreate()
Функция объявлена в файле coresrv/io/dma.h
.
Retcode KnIoDmaCreate(rtl_uint32_t order, rtl_size_t size, DmaAttr flags,
Handle *outRid);
Функция регистрирует и выделяет физический DMA-буфер.
Входные параметры:
order
– минимальный допустимый порядок выделения DMA-блоков; фактический порядок каждого блока в DMA-буфере выбирается ядром (но не будет меньше order) и помещается в дескриптор блока; порядок блока определяет число страниц в нем: блок с порядком N состоит из 2^N страниц;size
– размер DMA-буфера в байтах (должен быть кратен размеру страницы); сумма размеров выделенных DMA-блоков будет не меньшеsize
;flags
– DMA-флаги.
Выходной параметр outRid
содержит дескриптор выделенного DMA-буфера.
В случае успеха функция возвращает rcOk.
Если DMA-буфер больше не используется, его необходимо освободить с помощью функции KnIoClose()
.
Пример
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()
Функция объявлена в файле coresrv/io/dma.h
.
Retcode KnIoDmaGetInfo(Handle rid, DmaInfo **outInfo);
Функция получает информацию о DMA-буфере с дескриптором rid
.
Выходной параметр outInfo
содержит информацию о DMA-буфере.
В случае успеха функция возвращает rcOk.
В отличие от KnIoDmaGetPhysInfo()
, параметр outInfo
содержит не физические, а IOMMU-адреса DMA-блоков.
KnIoDmaGetPhysInfo()
Функция объявлена в файле coresrv/io/dma.h
.
Retcode KnIoDmaGetPhysInfo(Handle rid, DmaInfo **outInfo);
Функция получает информацию о DMA-буфере с дескриптором rid
.
Выходной параметр outInfo
содержит информацию о DMA-буфере.
В случае успеха функция возвращает rcOk.
В отличие от KnIoDmaGetInfo()
, параметр outInfo
содержит не IOMMU-адреса, а физические адреса DMA-блоков.
KnIoDmaMap()
Функция объявлена в файле coresrv/io/dma.h
.
Retcode KnIoDmaMap(Handle rid, rtl_size_t offset, rtl_size_t length, void *hint,
int vmflags, void **addr, Handle *handle);
Функция отображает участок DMA-буфера на адресное пространство процесса.
Входные параметры:
rid
– дескриптор выделенного с помощьюKnIoDmaCreate()
DMA-буфера;offset
– странично-выровненное смещение начала участка от начала буфера в байтах;length
– размер участка; должен быть кратен размеру страницы и не превышать <размер буфера -offset
>;hint
– виртуальный адрес начала отображения; если он равен 0, адрес выберет ядро;vmflags
– флаги аллокации.
В параметре vmflags
можно использовать следующие флаги аллокации (vmm/flags.h
):
- VMM_FLAG_READ и VMM_FLAG_WRITE – атрибуты защиты памяти;
- VMM_FLAG_LOW_GUARD и VMM_FLAG_HIGH_GUARD – добавление защитной страницы перед и после выделенной памяти соответственно.
Допустимые комбинации атрибутов защиты памяти:
- VMM_FLAG_READ – разрешено чтение содержимого страницы;
- VMM_FLAG_WRITE – разрешено изменение содержимого страницы;
- VMM_FLAG_READ | VMM_FLAG_WRITE – разрешено чтение и изменение содержимого страницы.
Выходные параметры:
addr
– указатель на виртуальный адрес начала отображенного участка;handle
– дескриптор созданного отображения.
В случае успеха функция возвращает rcOk.
Пример использования – см. KnIoDmaCreate().
Чтобы удалить созданное отображение, необходимо вызвать функцию KnIoClose()
, передав в нее дескриптор отображения handle
.