Oracle® Solaris 11.2 デバイスドライバの記述

印刷ビューの終了

更新: 2014 年 9 月
 
 

プライベート DMA バッファーの割り当て

一部のデバイスドライバでは、ユーザースレッドやカーネルから要求された転送を実行するのに加え、DMA 転送用のメモリーを割り当てることが必要になる場合があります。プライベート DMA バッファーを割り当てる例として、デバイスとの通信用の共有メモリーを設定したり、中間転送バッファーを割り当てたりすることが挙げられます。DMA 転送用のメモリーを割り当てるには、 ddi_dma_mem_alloc(9F) を使用します。

int ddi_dma_mem_alloc(ddi_dma_handle_t handle, size_t length,
    ddi_device_acc_attr_t *accattrp, uint_t flags,
    int (*waitfp)(caddr_t), caddr_t arg, caddr_t *kaddrp,
    size_t *real_length, ddi_acc_handle_t *handlep);

ここでは:

handle

DMA ハンドルです

length

目的とする割り当ての長さ (バイト単位) です

accattrp

デバイスアクセス属性構造体へのポインタです

flags

データ転送モードフラグです。使用できる値は、DDI_DMA_CONSISTENT DDI_DMA_STREAMING です。

waitfp

リソース割り当てエラーに対処するためのコールバック関数のアドレスです。 ddi_dma_alloc_handle(9F) のマニュアルページを参照してください。

arg

コールバック関数に渡される引数です

kaddrp

割り当てられたストレージのアドレスを含む正常な復帰へのポインタです

real_length

割り当てられた長さ (バイト単位) です

handlep

データアクセスハンドルへのポインタです

デバイスが非順次方式でアクセスする場合、flags パラメータは DDI_DMA_CONSISTENT に設定されます。 ddi_dma_sync(9F) を使用する同期段階は、小さなオブジェクトに頻繁に適用されるため、できるだけ軽量にします。このようなアクセスは一般に、一貫性アクセスと呼ばれています。一貫性アクセスは、デバイスとドライバ間の通信に使用される入出力パラメータブロックに特に役立ちます。

x86 プラットフォームでは、物理的に連続したメモリーである DMA メモリーを割り当てる際に次の要件があります。

  • ddi_dma_attr(9S) 構造体に含まれる scatter/gather リスト dma_attr_sgllen の長さを 1 に設定する必要がある。

  • DDI_DMA_PARTIAL を指定しない。DDI_DMA_PARTIAL を指定すると、部分的なリソース割り当てが可能になります。

次の例は、IOPB メモリーと、そのメモリーへのアクセスに必要な DMA リソースの割り当て方法を示しています。DMA リソースを引き続き割り当て、DDI_DMA_CONSISTENT フラグを割り当て関数に渡す必要があります。

使用例 9-3  ddi_dma_mem_alloc(9F) の使用
if (ddi_dma_mem_alloc(xsp->iopb_handle, size, &accattr,
    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &xsp->iopb_array,
    &real_length, &xsp->acchandle) != DDI_SUCCESS) {
    /* error handling */
    goto failure;
}
if (ddi_dma_addr_bind_handle(xsp->iopb_handle, NULL,
    xsp->iopb_array, real_length,
    DDI_DMA_READ | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
    NULL, &cookie, &count) != DDI_DMA_MAPPED) {
    /* error handling */
    ddi_dma_mem_free(&xsp->acchandle);
    goto failure;
}

メモリー転送が順次、単方向、ブロックサイズ、およびブロック整列の方式で行われる場合、flags パラメータは DDI_DMA_STREAMING に設定されます。このようなアクセスは一般に、ストリーミングアクセスと呼ばれています。

場合によっては、入出力キャッシュを使用すると入出力転送の速度を上げることができます。入出力キャッシュは、最低でも 1 つのキャッシュラインを転送します。ddi_dma_mem_alloc(9F) ルーチンでは、データの破壊を避けるために size を四捨五入してキャッシュラインの倍数にします。

ddi_dma_mem_alloc(9F) 関数は、割り当てられたメモリーオブジェクトの実際のサイズを返します。パディングと配置の要件のために、実際のサイズは要求されたサイズよりも大きくなることがあります。ddi_dma_addr_bind_handle(9F) 関数には実際の長さを指定する必要があります。

ddi_dma_mem_alloc(9F) で割り当てられたメモリーを解放するには、ddi_dma_mem_free(9F) 関数を使用します。


注 - ドライバは、バッファーが適切に配置されるようにする必要があります。下方バインドされた DMA バッファーの配置要件が設定されているデバイスのドライバは、それらの要件を満たすドライバの中間バッファーにデータをコピーしてから、その中間バッファーを DMA 用の DMA ハンドルにバインドすることが必要な場合があります。ドライバの中間バッファーを割り当てるには、 ddi_dma_mem_alloc(9F) を使用します。アクセスするデバイスにメモリーを割り当てるには、kmem_alloc (9F) ではなく、必ず ddi_dma_mem_alloc(9F) を使用します。