Скажем, у меня есть некоторый физический адрес (это автобус расположение моего источника DMA периферийный):Linux: как определить адрес DMA, соответствующий что вернулся из ioremap
phys_addr = 0xffff0000;
и я:
virt_addr = ioremap(phys_addr, PAGE_SIZE);
И после этого у меня больше нет прямого доступа к phys_addr
(в моем случае у меня нет доступа, потому что водитель, которого я пишу, прошел только virt_addr
).
Моя первая неудачная попытка:
wrong_phys_addr = virt_to_dma(dev,virt_addr);
Как и в сторону, я понятия не имею, почему устройство dev
является Релевент в этом поиска ...
Это, конечно, не работает, потому что virt_addr
не является прямой память ядра. DMA-API, по-видимому, предполагает, что все переводы, отличные от virt_to_bus
, устарели, и каждый должен использовать dma_map_single
и тому подобное, чтобы получить адрес шины DMA. Поэтому я в следующий раз пробовал это:
wrong_phys_addr = dma_map_single(dev, virt_addr, size, DMA_FROM_DEVICE);
Снова это все еще не работает. Конечно, если я использую 0xffff0000
непосредственно в качестве исходного адреса DMA на device_prep_dma_memcpy
, все работает отлично - но опять я не могу этого сделать, потому что у меня нет прямого доступа к нему. Единственный возможный способ получить его - это ходить по страницам страниц ядра ... Я действительно не хочу, чтобы это делать вручную. Есть ли способ лучше?
UPDATE
struct page *kmap_to_page(void * vaddr)
выглядит многообещающим. Я не уверен, что виртуальные адреса, возвращенные с ioremap, будут работать с этим. Другая возможность:
struct page* vmalloc_to_page(void* vmalloc_addr)
Мне нужно дополнительно исследовать.
Физические адреса не обязательно совпадают с адресами DMA. Во всяком случае, 'dma_map_single()' должен работать. И почему драйвер не имеет доступа к ресурсам своего устройства? –