[stackoverflow] Linux DMAドライバのインスタンス化および利用方法

  • 7
    Like
  • 0
    Comment
More than 1 year has passed since last update.

[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