• 検索結果がありません。

Contiguous Buffer (連続バッファ) DMA の実装

ドキュメント内 WinDriver v11.70 ユーザーズ ガイド (ページ 79-82)

第 9 章 実行に当たっての問題

9.1 DMA の実行

9.1.2 Contiguous Buffer (連続バッファ) DMA の実装

次のサンプル ルーチンは WinDriver の WDC API を使用して連続 DMA バッファを割り当て、バスマスタ DMA 転送を実行します。

ハードウェア独自の連続 DMA の詳細な例は、以下の拡張サポートを提供しているチップセット [第 8 章 ] のサンプル ライブラリ ファイルを参照してください:

 PLX – WinDriver\plx\lib\plx_lib.c および

WinDriver\plx\diag_lib\plx_diag_lib.c (plx_lib.c DMA API を使用)

 Xilinx Bus Master DMA (BMD) デザイン - WinDriver\xilinx\bmd_design\bmd_lib.c Contiguous Buffer (連続バッファ) DMA 実装のサンプル

BOOL DMARoutine(WDC_DEVICE_HANDLE hDev, DWORD dwDMABufSize,

UINT32 u32LocalAddr, DWORD dwOptions, BOOL fPolling, BOOL fToDev) {

PVOID pBuf = NULL;

WD_DMA *pDma = NULL;

BOOL fRet = FALSE;

/* Allocate a DMA buffer and open DMA for the selected channel */

if (!DMAOpen(hDev, &pBuf, u32LocalAddr, dwDMABufSize, fToDev, &pDma)) goto Exit;

/* Enable DMA interrupts (if not polling) */

if (!fPolling) {

if (!MyDMAInterruptEnable(hDev, MyDmaIntHandler, pDma)) goto Exit; /* Failed enabling DMA interrupts */

}

/* Flush the CPU caches (see documentation of WDC_DMASyncCpu()) */

WDC_DMASyncCpu(pDma);

/* Start DMA - write to the device to initiate the DMA transfer */

MyDMAStart(hDev, pDma);

/* Wait for the DMA transfer to complete */

MyDMAWaitForCompletion(hDev, pDma, fPolling);

/* Flush the I/O caches (see documentation of WDC_DMASyncIo()) */

WDC_DMASyncIo(pDma);

fRet = TRUE;

Exit:

DMAClose(pDma, fPolling);

return fRet;

}

/* DMAOpen: Allocates and locks a Contiguous DMA buffer */

BOOL DMAOpen(WDC_DEVICE_HANDLE hDev, PVOID *ppBuf, UINT32 u32LocalAddr, DWORD dwDMABufSize, BOOL fToDev, WD_DMA **ppDma)

{

DWORD dwStatus;

DWORD dwOptions = fToDev ? DMA_TO_DEVICE : DMA_FROM_DEVICE;

/* Allocate and lock a Contiguous DMA buffer */

dwStatus = WDC_DMAContigBufLock(hDev, ppBuf, dwOptions, dwDMABufSize, ppDma);

if (WD_STATUS_SUCCESS != dwStatus) {

printf("Failed locking a Contiguous DMA buffer. Error 0x%lx - %s\n",

dwStatus, Stat2Str(dwStatus));

return FALSE;

}

/* Program the device's DMA registers for the physical DMA page */

MyDMAProgram((*ppDma)->Page, (*ppDma)->dwPages, fToDev);

return TRUE;

}

/* DMAClose: Frees a previously allocated Contiguous DMA buffer */

void DMAClose(WD_DMA *pDma, BOOL fPolling) {

/* Disable DMA interrupts (if not polling) */

if (!fPolling)

MyDMAInterruptDisable(hDev);

/* Unlock and free the DMA buffer */

WDC_DMABufUnlock(pDma);

}

必要な実装

上記のサンプル コードで、対象のデバイスの仕様に応じて、以下の MyDMAxxx() ルーチンを実装します。

 MyDMAProgram(): デバイスの DMA レジスタをプログラムします。

詳細は、デバイスのデータシートを参照してください。

 MyDMAStart(): デバイスへ書き込みをして、DMA 転送を開始します。

 MyDMAInterruptEnable() と MyDMAInterruptDisable(): WDC_IntEnable() と WDC_IntDisable() を使用して、ソフトウェアの割り込みを有効または無効にし、デバイスの関 連するレジスタを書き込みまたは読み込みをして、物理的にハードウェアの DMA 割り込みを有効 または無効にします。(WinDriver での割り込み処理に関する詳細はセクション 9.2 を参照してくだ さい) 。

 MyDMAWaitForComplete(): 転送の完了をデバイスにポーリングするか、”DMA DONE”

(DMA の完了) 割り込みを待機します。

9.1.2.1 Windows で連続 DMA バッファの事前割り当て

WinDriver では、DMA API を使用して割り当て可能な DMA バッファのサイズに制限はありま せん。ただし、DMA の割り当て処理は、割り当て時の利用可能なシステム リソースの量に依存し

ます。そのため、バッファをより速く割り当てれば、より良い割り当てができます。

WinDriver for Windows では、対象のデバイスの INF ファイルを編集して、起動時に連続 DMA バッ ファを再割り当てすることができます。これによって、割り当てに成功する確度を上げます。

注意: host-to-device のバッファおよび / または device-to-host へのバッファの 2 方向のバッファのいずれれ の最大値、または 2 方向のバッファに事前割り当てができます。

Windows で連続 DMA バッファを事前に割り当てるには、以下の手順で行います:

1. 以下のように、対象のデバイス INF ファイルの [UpdateRegistryDevice] レジストリ キー以下に必 要な設定を追加します。

注意:

 以下、二つのバッファの事前割り当ての設定の例です (一方向まはた二方向のいずれか 一方、ただし、もちろん一つのバッファのみ (またはまったくなし) を事前割り当てすること もできます。

 DriverWizard で生成したデバイスの INF ファイルおよび WinDriver のサンプルに含まれ

るデバイスの INF ファイルには、既に一方向のバッファの設定行が含まれているので、各 行の最初のコメント (‘;’) を削除し、二方向のバッファの場合には、DMA 方向のフラグを 変更し、タイトルのコメントを編集する必要があります。

 一方向のバッファを事前割り当てするには、以下の行を追加します:

; Host-to-device DMA buffer:

;HKR,,"DmaToDeviceBytes",0x00010001,0x100000 ; Buffer size, in bytes

;HKR,,"DmaToDeviceOptions",0x00010001,0x41 ; DMA flags (0x40=DMA_TO_DEVICE

; +

0x1=DMA_KERNEL_BUFFER_ALLOC)

; Device-to-host DMA buffer:

;HKR,,"DmaFromDeviceBytes",0x00010001,0x100000 ; Buffer size, in bytes

;HKR,,"DmaFromDeviceOptions",0x00010001,0x21 ; DMA flags

; (0x20=DMA_FROM_DEVICE + ;

0x1=DMA_KERNEL_BUFFER_ALLOC)

 二方向のバッファを事前割り当てするには、以下の行を追加します:

; Bidirectional DMA buffer:

;HKR,,"DmaToDeviceBytes",0x00010001,0x100000 ; Buffer size, in bytes

;HKR,,"DmaToDeviceOptions",0x00010001,0x61 ; DMA flags

; (0x60=DMA_TO_FROM_DEVICE

; +

0x1=DMA_KERNEL_BUFFER_ALLOC)

; Second bidirectional DMA buffer:

;HKR,,"DmaFromDeviceBytes",0x00010001,0x100000 ; Buffer size, in bytes

;HKR,,"DmaFromDeviceOptions",0x00010001,0x61 ; DMA flags

; (0x60=DMA_TO_FROM_DEVICE

; +

0x1=DMA_KERNEL_BUFFER_ALLOC)

 注意: 二方向のバッファの INF ファイルの設定では、一方向のバッファと同じレジストリ キーを 使用します (DmaToDeviceXXX と DmaFromDeviceXXX)、ただし、DMA オプション キーの 値(DmaToDeviceOptions / DmaFromDeviceOptions) は DMA_TO_FROM_DEVICE フ ラグ(0x06) を設定してください (DMA_TO_DEVICE (0x04) または DMA_FROM_DEVICE (0x20) フラグではなく)。

2. 必要に応じて、INF ファイルのバッファ サイズを編集し、オプション マスクへフラグを追加します。ただ し、上記の手順 1 の説明の通り、方向のフラグと DMA_KERNEL_BUFFER_ALLOC フラグを設定す る必要があるので、注意してください。

3. 注意: WinDriver でサポートする DMA フラグに関しては、別紙の WD_DMA 構造体の dwOptions フィールドの説明を参照してください。INF ファイルに設定する関連するフラグの値を探すには、

WinDriver\include\windrvr.h フ ァ イ ル の フ ラ グ の 定 義 を 参 照 し て く だ さ い; (た と え ば 、 DMA_KERNEL_BUFFER_ALLOC フラグを含む enum を探すなど)。

4. コードでは、連続 DMA ロック関数 (WDC_DMAContigBufLock()) への最初の呼び出しまたは最初 の二つの呼び出しでは、INF ファイルのバッファ設定に一致するパラメータの値を設定してください。

device-to-host のバッファまたは最初の二方向のバッファの割り当ての場合、DMA オプション

マスクのパラメータ (dwOptions) には、DmaFromDeviceOptions レジストリ キーの値に同 じ フ ラグ 設 定 を 設 定 す る必 要 が あ り 、 バ ッ フ ァ サイ ズ の パ ラメ ー タ (dwDMABufSize) を DmaFromDeviceBytes レジストリ キーの値に設定する必要があります。

host-to-device のバッファまたは二番目の二方向のバッファの割り当ての場合、DMA オプ

ション マスクのパラメータ (dwOptions) には、DmaToDeviceOptions レジストリ キーの値に 同じフラグ設定を設定する必要があり、バッ ファ サイズのパラメータ (dwDMABufSize) を DmaToDeviceBytes レジストリ キーの値に設定する必要があります。

 注意:

 WDC_DMAContigBufLock() を使用する場合、DMA_KERNEL_BUFFER_ALLOC フラグ

(INF ファイルの設定では設定する必要がある) を明示的に設定する必要はありません (関数 が自動的にこのフラグを設定するので)。

 低 レ ベ ル な WinDriver の WD_DMALock() 関 数 を 使 用 す る 場 合 、 関 数 の

pDma->dwOptions パラメータに DMA オプションを設定し (DMA_KERNEL_BUFFER_ALLOC フ

ラグも設定する必要があります)、pDma->dwBytes パラメータにバッファ サイズを設定する必 要があります。

 十分なリソースがないために事前割り当てに失敗する場合、非ページ プールのサイズを増 やす必要があります (メモリの割り当てから)。

ドキュメント内 WinDriver v11.70 ユーザーズ ガイド (ページ 79-82)