Posted at

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

More than 5 years have 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