[Q]
我々は、Zynq上で、たくさんのデータを素早く処理するために、カスタムのDMAデバイスを
動かしている。ベアメタルでは、すべてうまく動かすことができた。でも、Linux上だとうまく動かない。
我々の環境は、ARM linuxカーネルのver.3.9だ。
今のところ、以下のコードの一部を使おうと考えている。
http://www.mjmwired.net/kernel/Documentation/DMA-API-HOWTO.txt
しかし、device構造体のインスタンス化のやり方に確信が持てない。
Thanks a lot!
[A]
xilinx_axidma.cのコードで考えてみる。
xdev->dev と chan->dev は、すでに &(op->dev)に初期化されている。
なので、xdev->dev と chan->devをDMA APIの最初のパラメタとして
渡すことができる。
xilinx_axidma.c.において、あなたがDMAバッファプールを作る必要はない。
一言で言えば、初期化は正しく行われているということだ。ここまでで、
DMA APIを使う準備はできている。
恐らく、あなたは単一のバッファではなく、Tx/Rxのリングバッファを作るんだろう。
FPGA上のDMAコントローラは、物理アドレスを使うのに対して、
カーネルモジュールは仮想アドレスを使う。
なので、バッファリング内のすべてのバッファに対するvaddrs/paddrs双方を
管理するなんらかの構造が必要となる。
(1) DMAバッファを確保する方法
vaddr = (unsigned long) dma_alloc_coherent(xdev->dev, size, paddr, GFP_KERNEL);
返値は、確保したDMAバッファの仮想アドレスで、paddrには対応する物理アドレスが
格納される。FPGA上にあるDMAコントローラはpaddrを使うが、カーネルモジュールは
vaddrを使う。
(2) FPGA側からデータを受け取った後に、Dキャッシュを無効にするための以下の関数を呼ぶ。
dma_unmap_single(xdev->dev, paddr, length, DMA_FROM_DEVICE);
ここで、paddrはDMAバッファの物理アドレスである。
(3) バッファ内容をFPGAに送る前に、Dキャッシュを吐き出すための以下の関数を呼ぶ。
paddr = dma_map_single(xdev->dev, vaddr, length, DMA_TO_DEVICE);
paddrはDMAバッファの物理アドレスで、vaddrはそのDMAバッファの仮想アドレスである。
(4) 受信バッファの物理アドレスを取得する
paddr = dma_map_single(xdev->dev, vaddr, length, DMA_FROM_DEVICE);
(5) DMAバッファの解放方法
dma_free_coherent(xdev->dev, size, vaddr, paddr);
ここで、vaddrはDMAバッファの仮想アドレスであるのに対して、paddrは物理アドレス。
--
http://stackoverflow.com/questions/17913679/how-to-instantiate-and-use-a-dma-driver-linux-module