LINUX.ORG.RU

Мапирование памяти для взаимодействия с устройством на PCI шине


0

2

Всем добрый вечер. Не мог бы кто пояснить технологию мапирования адресов из физических в виртуальные и наоборот. Стоит задача: Есть некоторое устройство на PCI шине, для обмена с которым считывается «физический адрес» из конфигурационного пространства PCI. Этот адрес указывает на структуры данных, с помощью которых и происходит взаимодействие (DMA). Главная структура должна содержать физические адреса на другие структуры и т.д. Мне необходимо заполнить эти структуры и в одной из них выставить бит, сигнализирующий устройству, что данные загружены в память DMA и оно может их обработать. Мало того, оно мне присылает ответ в этих же структурах. Проблема в том, что я не могу работать с физическими адресами напрямую, а устройство не может работать с виртуальными адресами. Не понимаю каков механизм мапирования/размапирования даной секции DMA памяти, подскажите пожалуйста...

Ответ на: комментарий от nanoolinux

я что-то для ядра давно уже ничего не писал, всё забыл нафиг. ты же для dma должен был память получать от pci_alloc_consistent()? он тебе виртуальный адрес этого куска и позвращает не?

nanoolinux ★★★★ ()
Ответ на: комментарий от nanoolinux

Понимаешь, виртуальный адрес я получаю, заполняю по нему данные и т.д. но устройство пишет только в физический адрес в непрерывный участок памяти, и этот адрес ему должен предоставить я... Когда обмен у меня с этим устройством начинается, я в структуре бит поднимаю, а, затем этот бит смотрю пока он не очистится, и он не очищается....Я не понимаю как правильно и самое главное когда мапировать и размапировать память, чтобы я мог с ней работать и устройство тоже, так как сказать сама технология мапирования не очень понятна

energyclab ()
Ответ на: комментарий от energyclab
...
dma_addr_t dma_addr; //this is physical address. should be given to dma engine of the device.
int dma_size = PAGE_SIZE*16; // requested size of dma memory
int *ptr; //this is virtual address.
ptr =(int *) pci_alloc_consistent(dev, dma_size, &dma_addr);
	
write_reg(DMA_OFFSET, dma_addr); //give address of consistently allocated dma memory to the device.

// job's done. now one must call pci_dma_sync_single_for_cpu() to work with the ptr (e.g. copy_to_user() in some char_read func) and pci_dma_sync_single_for_device() to make it possible access from device side.
...

write_reg приблизительно такой:

static void write_reg(u32 dw_offset, u32 val)
{
	writel(val, bar0_virt_addr + 4 * dw_offset);
	readl(bar0_virt_addr + 4 * dw_offset);
}

http://lwn.net/2001/0712/a/dma-interface.php3 рекомендую почитать.

nanoolinux ★★★★ ()
Ответ на: комментарий от energyclab

а бит этот где находится? если в dma памяти, то тебе надо сначала dma write сделать, (предполагаю, дождаться прерывания), а потом dma read. и только тогда битик смотреть. не забывая при этом про pci_dma_sync_single_for_{cpu,device}.

nanoolinux ★★★★ ()

Юзерспейс?

mv ★★★★★ ()
Ответ на: комментарий от nanoolinux

Понимаешь в чем дело, я загружен не из под операционки, а из под специальной программы, которая контролирует все железо и доступ к нему(в простонародье - гипервизор), т.е. когда устройство работает с физической памятью, ему доступ разрешен, а когда я работаю с физической памятью меня эта прога лочит... Я должен мапировать память для работы с этим устройством... У меня есть главная структура А в которой лежит переменная, хранящая адрес на структуру Б (int - тип переменной). В свою очередь структура Б имеет переменную, хранящую адрес на структуру С. В этой структуре есть переменные, куда загружается адрес полезной нагрузки (полезная нагрузка тоже находится в физической памяти и это просто данные для передачи). Помимо загрузки полезной нагрузки в структуру С еще грузятся спец данные (чтобы устройство поняло что я от него хочу) в структуру Б, так же само устройство обновляет некоторые поля структуры А. После того, как все данные подготовлены к передаче в структуре Б устанавливается бит в 1 и устройство начинает выполнять команду, я же ожидаю когда этот бит сбросится в 0.

Без гипервизора мой драйвер работает на ура напрямую с физической памятью, с гипервизором же при первом обращении по физическому адресу в ОП меню вырубают. Для решения этой проблемы я воспользовался функциями мапирования памяти, предоставляемые гипервизором... Меня вырубать перестало, одного в структуре Б после установки бита в 1, он не сбрасывается устройством... Я так думаю что это из за неправльного применения мапирования....

energyclab ()
Ответ на: комментарий от energyclab

Проверь атрибуты кэширования. Должно быть uncached.

mv ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.