LoginSignup
10
16

More than 5 years have passed since last update.

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

Posted at

[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

10
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
16