BUS_DMA(9) | FreeBSD Kernel Developer's Manual | BUS_DMA(9) |
名称
bus_dma, bus_dma_tag_create, bus_dma_tag_destroy, bus_dmamap_create, bus_dmamap_destroy, bus_dmamap_load, bus_dmamap_load_bio, bus_dmamap_load_ccb, bus_dmamap_load_mbuf, bus_dmamap_load_mbuf_sg, bus_dmamap_load_uio, bus_dmamap_unload, bus_dmamap_sync, bus_dmamem_alloc, bus_dmamem_free — バスとマシン独立 DMA マッピングインタフェース書式
#include < machine/bus.h> int
bus_dma_tag_create( bus_dma_tag_t parent, bus_size_t alignment, bus_addr_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, bus_dma_filter_t *filtfunc, void *filtfuncarg, bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, void *lockfuncarg, bus_dma_tag_t *dmat);
int
bus_dma_tag_destroy( bus_dma_tag_t dmat);
int
bus_dmamap_create( bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp);
int
bus_dmamap_destroy( bus_dma_tag_t dmat, bus_dmamap_t map);
int
bus_dmamap_load( bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, int flags);
int
bus_dmamap_load_bio( bus_dma_tag_t dmat, bus_dmamap_t map, struct bio *bio, bus_dmamap_callback_t *callback, void *callback_arg, int flags);
int
bus_dmamap_load_ccb( bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb, bus_dmamap_callback_t *callback, void *callback_arg, int flags);
int
bus_dmamap_load_mbuf( bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *mbuf, bus_dmamap_callback2_t *callback, void *callback_arg, int flags);
int
bus_dmamap_load_mbuf_sg( bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *mbuf, bus_dma_segment_t *segs, int *nsegs, int flags);
int
bus_dmamap_load_uio( bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, bus_dmamap_callback2_t *callback, void *callback_arg, int flags);
void
bus_dmamap_unload( bus_dma_tag_t dmat, bus_dmamap_t map);
void
bus_dmamap_sync( bus_dma_tag_t dmat, bus_dmamap_t map, op);
int
bus_dmamem_alloc( bus_dma_tag_t dmat, void **vaddr, int flags, bus_dmamap_t *mapp);
void
bus_dmamem_free( bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map);
解説
Direct Memory Access (DMA) は、CPU を必要としないで、データを転送する方法で、その結果、より高い性能を提供します。 DMA トランザクションは、デバイスからメモリ、デバイスからデバイス、またはメモリからメモリの間で達成することができます。bus_dma API は、DMA メカニズムへのバス、デバイス、マシンから独立 (MI) のインタフェースです。 DMA マッピングの設定、キャッシュ問題の操作、バス特有の機能と制限のようなマシン依存の問題を抽象化することによって柔軟性と簡潔さをクライアントに提供します。
構造体とタイプ
- bus_dma_tag_t
- DMA トランザクションの特性について記述するマシン依存 (MD) 不透明な (サイズ及び形がわからない) タイプ。 DMA タグは、各子供のタグが親の制限を引き継いで、階層構造に体系化されています。これで、DMA トランザクションのパスに沿ったすべてのデバイスがそれらのトランザクションの制約を与えることを許します。
- bus_dma_filter_t
-
クライアントの指定されたアドレスフィルタは、次の形式があります:
- int
- client_filter( void *filtarg, bus_addr_t testaddr)
DMA アドレス制限が、1 つのウィンドウによって指定できない、デバイスに許されたタグ作成の間にアドレスフィルタを、指定することができます。 filtarg 引数は、コールバックのすべての呼び出しに渡されるタグ作成の間にクライアントによって指定されます。 testaddr 引数は、 DMA マッピングの潜在的な開始アドレスを含んでいます。フィルタ関数は、 testaddr から‘
trunc_page(testaddr) + PAGE_SIZE - 1
’までのアドレスのセットで機能します。フィルタ関数は、この範囲の任意のマッピングがデバイスによって適合することができるなら、0 を返すべきです、そうでなければ、0 以外を返すべきです。 - bus_dma_segment_t
-
個々の DMA セグメントを記述するマシン依存タイプ。それは、次のフィールドを含んでいます:
bus_addr_t ds_addr; bus_size_t ds_len;
ds_addr フィールドは、DMA セグメントのデバイスの可視アドレスを含み、 ds_len は、DMA セグメントの長さを含みます。マッピング呼び出しによって返された DMA セグメントは、成功する DMA 操作に必要なすべての制限を順守するしますがが、何らかの変換 (例えば、ホストのバイト順からデバイスのバイト順の変換) は、デバイスへのセグメント情報を提示するとき、ほとんど常に必要とされます。
- bus_dmamap_t
- 個々のマッピングについて記述するマシン依存の不透明なタイプ。 1 つのマップは、ロードされる各メモリ割り付けに使用されます。それらがいったんアンロードされると、マップを再利用することができます。複数のパップを、1 つの DMA タグに関連づけることができます。マップの値が、一定の条件の下のいくつかでプラットフォームで NULL に評価しているとはいえ、すべての場合に NULL になると決して仮定されるべきではありません。マップの値が特定の条件の下で、いくつかでプラットフォームにおいて NULL と評価する間に、すべての場合において、それが NULL になると決して仮定するべきではありません。
- bus_dmamap_callback_t
-
bus_dmamap_load(),
bus_dmamap_load_bio() または
bus_dmamap_load_ccb() を通して
bus_dmamap_t のロードから生じる受信マッピング情報のために指定されたクライアントのコールバック。コールバックは、次の形式です:
- void
- client_callback( void *callback_arg, bus_dma_segment_t *segs, int nseg, int error)
callback_arg は、dmamap ロード関数に渡されたコールバック引数です。 segs と nseg 引数は、マッピングを表す bus_dma_segment_t 構造体の配列を表現します。この配列は、コールバック関数の範囲内でのみ有効です。マッピングの成否は、 error 引数によって示されます。コールバックの使用に関する詳しい情報は、個々の dmamap ロード関数の記述で見つけることができます。
- bus_dmamap_callback2_t
-
bus_dmamap_load_uio() または
bus_dmamap_load_mbuf() を通して
bus_dmamap_t のロードから生じる情報をマッピングしながら受信するためのコールバックを指定するクライアント。
Callback2s は、次の形式です:
- void
- client_callback2( void *callback_arg, bus_dma_segment_t *segs, int nseg, bus_size_t mapsize, int error)
Callback2 の振る舞いは、 mapsize を通して提供されるマップされたデータの長さを追加した bus_dmamap_callback_t と同じです。
- bus_dmasync_op_t
-
メモリ同期操作指定子。バス DMA は、メモリの一貫性を保証するためにそのデバイスの目に見えるマッピングでメモリの明白な同期を必要とします。
bus_dmasync_op_t によって、実行されるか、実行したことがある DMA 操作のタイプは、正しい一貫性のある対策を取ることができるように、システムと通信することができます。操作は、一緒に組み合わせることができるビットフィールドのフラグとして表されますが、両方ではなく、 PRE フラグまたは POST フラグを組み合わせることに意味があります。どのようにこれらの操作を使用するかの詳細については、下記の
bus_dmamap_sync() の説明を参照してください。
以下に指定されたすべての操作は、デバイスからホストメモリまで来るデータを意味する読み込み、と、ホストメモリからデバイスまで行くデータを意味する書き込みである、ホストメモリの観点から実行されます。もう一つの方法として、 bus_dma での読み込み操作に対応するネットワークパケットか、または記憶域セクタを読み込むところで、ドライバ操作の点から見て操作を考えることができます。
- BUS_DMASYNC_PREREAD
- デバイスによってホストメモリの更新の前に要求された任意の同期を実行します。
- BUS_DMASYNC_PREWRITE
- CPU によるホストメモリの更新の後でホストメモリへのデバイスのアクセスの前に要求された任意の同期を実行します。
- BUS_DMASYNC_POSTREAD
- デバイスによってホストメモリの更新の後で、ホストメモリへの CPU アクセスの前に要求された任意の同期を実行します。
- BUS_DMASYNC_POSTWRITE
- ホストメモリへのデバイスのアクセスの後に要求された任意の同期を実行します。
- bus_dma_lock_t
-
ロック/ミューテックス操作メソッドを指定するクライアント。これは、クライアントロックが、操作される必要があるときはいつでも、 busdma から呼び出されます。現在の形式では、関数は、
BUS_DMA_LOCK で延期され
BUS_DMA_UNLOCK で直後である DMA ロード操作のためのコールバックの直前に呼び出されます。ロード操作が延期される必要がないなら、マップをロードする関数が適切なロックを保持するべきであるので、それは、呼び出されません。このメソッドは、次の形式です:
- void
- lockfunc( void *lockfunc_arg, bus_dma_lock_op_t op)
lockfuncarg 引数は、コールバックのすべての呼び出しに渡されるようにタグ作成の間に、クライアントによって指定されます。 op 引数は、実行するロック操作を指定します。
2 つの lockfunc 実装は、便宜のために提供されています。 busdma_lock_mutex() は、 lockfuncarg を通して提供されたスリープミューテックスで標準のミューテックス操作を実行します。 dflt_lock() は、それが呼び出されるなら、システムパニックを生成します。それは、 lockfunc が NULL として bus_dma_tag_create() に渡されるとき、タグに代入され、延期されたロード操作で使用されるべきでないタグのために役に立ちます。
- bus_dma_lock_op_t
-
クライアントによって指定された
lockfunc() によって実行される操作。
- BUS_DMA_LOCK
- クライアントロックプリミティブを獲得する、そして/または、ロックします。
- BUS_DMA_UNLOCK
- クライアントロックプリミティブを解放する、そして/または、アンロックします。
関数
- bus_dma_tag_create( parent, alignment, boundary, lowaddr, highaddr, *filtfunc, *filtfuncarg, maxsize, nsegments, maxsegsz, flags, lockfunc, lockfuncarg, *dmat)
-
デバイス特有の DMA タグを割り付けて、次の提供された引数に従って、それを初期化します:
- parent
- 親のブリッジ、CPU メモリとデバイスの間の制限を示します。各デバイスは、 bus_get_dma_tag() を呼び出すことによって、マスタ親タグを使用しなければなりません。
- alignment
- このタグを使用して作成された任意のマッピングのバイト単位の整列制約。整列は、2 の冪乗でなければなりません。 DMA がどんなアドレスでも始まることができるハードウェアは、バイト整列に 1 を指定するでしょう。 4K の倍数で始まる DMA 転送を必要とするハードウェアは、 4096 を指定するでしょう。
- boundary
-
ターゲット DMA メモリ領域のバイト単位の境界制約。境界は、アドレスのセット、単一の
bus_dma_segment_t によって交差することができない境界引数のすべての倍数を示します。境界は、2 の冪乗でなければならなくで、最大のセグメントサイズより小さくなってはいけません。‘
0
’は、境界制約がないことを示します。 - lowaddr, highaddr
-
デバイスによって直接アクセスすることが
できない バスアドレス空間のウィンドウの領域。ウィンドウは、
lowaddr より大きくて、
highaddr 以下のすべてのアドレスを含んでいます。例えば、4GB より上の DMA の能力がないデバイスは、
BUS_SPACE_MAXADDR の
highaddr と
BUS_SPACE_MAXADDR_32BIT の
lowaddr を指定するでしょう。同様に、16MB より下のアドレスのみに DMA を実行できるデバイスは、
BUS_SPACE_MAXADDR の
highaddr と
BUS_SPACE_MAXADDR_24BIT の
lowaddr を指定するでしょう。いくつかの実装は、ウィンドウの外にある利用可能なホストメモリをオーバラップして、デバイスの目に見えるアドレス空間の何らかの領域を必要とします。‘
安全なメモリ
’のこの領域は、そうでなければ排除ウィンドウと衝突する要求を跳ね返すために使用されます。 - filtfunc
- メモリを lowaddr と highaddr によって表現されるウィンドウにマップする試みのために呼び出されるオプションのフィルタ関数 ( NULL も可)。 lowaddr と highaddr によって表現された単一のウィンドウが適切にデバイスの制約を記述することができないとき、フィルタ関数のみ要求されます。フィルタ関数は、排除ウィンドウをオーバラップする、あらゆるマシンページのために呼び出されます。
- filtfuncarg
- すべてに渡された引数は、このタグのためのフィルタ関数を呼び出します。 NULL も可。
- maxsize
- このタグに関連している与えられた DMA マッピングでのすべてのセグメントの長さの合計のバイト単位の最大サイズ。
- nsegments
- DMA にマップされた領域に許された (セグメントを散乱/収集する) 不連続の数。制限がなければ、 BUS_SPACE_UNRESTRICTED が指定できます。
- maxsegsz
- dmat に関連している任意の DMA にマップされた領域のセグメントのバイト単位の最大サイズ。
- flags
-
次の通りです:
- BUS_DMA_ALLOCNOW
- このタグで少なくとも 1 つのマップロード操作を取り扱うために十分なリソースを前もって割り付けます。十分なリソースが利用可能でないなら、 ENOMEM が返されます。 bus_dmamem_alloc() で割り付けられるバッファを記述するのみであるタグに、これを使用するべきではありません。また、他のタグがあるリソース共有のために、このフラグは、リソースがこのタグを排他的に割り付けるか、または予約することを保証しません。それは、単に小さな最適化として取り扱われるべきです。
- lockfunc
- busdma がクライアントの代わりにロックを操作する必要があるとき、呼び出されるオプションのロック操作関数 ( NULL も可)。 NULL が指定されるなら、 dflt_lock() が使用されます。
- lockfuncarg
- lockfunc によって指定された関数へ渡されるオプションの引数。
- dmat
- 結果の DMA タグが格納される bus_dma_tag_t へのポインタ。
タグの作成またマッピングリソースを割り付けのために十分なメモリが利用可能でないなら、 ENOMEM を返します。
- bus_dma_tag_destroy( dmat)
-
bus_dma_tag_create() によって作成された DMA タグ
dmat の割り付けを解放します。
任意の DMA マップが dmat に関連していたままで残っているなら、 EBUSY を返すか、または、成功すれば、‘
0
’を返します。 - bus_dmamap_create( dmat, flags, *mapp)
-
DMA マップを割り付けて、初期化します。引数は、次の通りです:
- dmat
- DMA タグ。
- flags
-
次の通りです:
- BUS_DMA_COHERENT
- キャッシュの sync 操作ができるだけ安価にできるように、このマップでロードされたメモリのマップを試みます。これらでロードされたメモリが、受信と送信バッファのようなストリーム可能なデータと対照的に、制御データのような頻度で、CPU と DMA エンジンの両方によってアクセスされるとき、このフラグは、通常マップに設定されます。このフラグの使用は、 bus_dmamap_sync() を使用する要件を取り除きませんが、これらの操作を実行するコストを削減するかもしれません。 bus_dmamap_create() に関して、 BUS_DMA_COHERENT フラグは、現在、sparc64 で実装されています。
- mapp
- 結果の DMA マップが格納される bus_dmamap_t へのポインタ。
マップを作成するか、またはマッピングのリソースを割り付けるために十分なメモリが利用可能でないなら、 ENOMEM を返します。
- bus_dmamap_destroy( dmat, map)
-
与えられた DMA マップに関連しているすべてのリソースを解放します。引数は、次の通りです:
- dmat
- map を割り付けるために使用される DMA タグ。
- map
- 破壊する DMA マップ。
マッピングが map のためにまだアクティブであるなら、 EBUSY を返します。
- bus_dmamap_load( dmat, map, buf, buflen, *callback, callback_arg, flags)
-
DMA マップ
map に関連づけられた
buflen バイトの
buf のデバイスの目に見えるアドレス空間においてマッピングを作成します。この呼び出しは、常に直ちに返り、いかなる理由でもブロックしません。引数は、次の通りです:
- dmat
- map を割り付けるために使用される DMA タグ。
- map
- 現在アクティブなマッピングのない DMA マップ。
- buf
- デバイスの目に見えるアドレス空間にマップされる、連続した (KVA) バッファへのカーネル仮想アドレスポインタ。
- buflen
- バッファのサイズ。
- callback callback_arg
- コールバック関数とその引数。いったん十分なマッピングリソースが DMA 操作に利用可能になると、この関数は、呼び出されます。リソースが一時的に利用可能でないなら、この関数は、後まで延期されますが、ロード操作は、いまだに直ちに読みだし側に返ります。したがって、呼び出し側は、コールバックがロードが返る前に呼び出されることを仮定するべきではありません、そしてコードは、これを取り扱うために適切に構造化されるべきです。この振る舞いを制御する特有のフラグとエラーコードに関しては、下記を参照してください。
- flags
-
次の通りです:
- BUS_DMA_NOWAIT
- ロードは、不十分なマッピングリソースの場合に延期するべきでなく、代わりに適切なエラーで直ちに返るべきです。
- BUS_DMA_NOCACHE
- 仮想ページと仮想ページからの生成されるトランザクションは、キャッシュ不可能です。 bus_dmamap_load() に関して、 BUS_DMA_NOCACHE フラグは、現在、sparc64 で実装されています。
呼び出し側への返り値は、次の通りです:
- 0
- コールバックが、呼び出されて、終了しました。マッピングの状態をコールバックに配送しました。
- EINPROGRESS
-
マッピングは、リソース不足によって延期されました。コールバックは、リソースが利用可能になるとすぐに呼び出されます。コールバックは、FIFO の順序でサービスされます。
特別なリソースを要求しない同じタグのための続くロード操作は、今でも成功することに注意してください。これは、要求の異なる順序の処理の結果となるかもしれません。呼び出し側が保存されている要求の順序を要求するなら、呼び出し側は、保留中の要求のコールバックが呼び出されるまで、続く要求を引き延ばすことを要求されます。
- ENOMEM
- ロード要求は、不十分なリソースのため失敗し、呼び出し側は、明確に BUS_DMA_NOWAIT フラグを使用しました。
- EINVAL
- ロード要求は、無効です。コールバックが呼び出され、同じエラーが与えれました。このエラー値は、 dmat, map, buf または callback が無効であるか、または buflen が、dma タグ dmat を作成するために使用される maxsize 引数より大きいことを示します。
コールバックが呼び出されるとき、マッピングの傾向を示すエラー値を提示します。エラーは、次の 1 つとなります:
- 0
- マッピングは、成功し、そして、 dm_segs コールバック引数は、マッピングについて記述する bus_dma_segment_t 要素の配列を含んでいます。この配列は、コールバック関数の範囲の間のみ有効です。
- EFBIG
- マッピングは、要求された割り付けサイズが maxsize より少なくても、タグで提供されたセグメント制約の中では、達成することができませんでした。
- bus_dmamap_load_bio( dmat, map, bio, callback, callback_arg, flags)
- これは、DMA 転送のための bio によって指されるバッファをマップする bus_dmamap_load() の変形です。 bio は、マップされているか、またはマップされていないバッファのいずれかを指します。
- bus_dmamap_load_ccb( dmat, map, ccb, callback, callback_arg, flags)
-
これは、DMA 転送のための
ccb によって指されるバッファをマップする
bus_dmamap_load() の変形です。
ccb のためのデータは、次のタイプのいずれかです:
- CAM_DATA_VADDR
- データは、単一の KVA バッファです。
- CAM_DATA_PADDR
- データは、単一のバスアドレス範囲です。
- CAM_DATA_SG
- データは、KVA バッファの scatter/gather (散乱/集結) リストです。
- CAM_DATA_SG_PADDR
- データは、バスアドレス範囲の scatter/gather (散乱/集結) リストです。
- CAM_DATA_BIO
- データは、CCB にアタッチされる struct bio に含まれています。
bus_dmamap_load_ccb() は、次の CCB XPT 機能コードをサポートしています:
- XPT_ATA_IO
- XPT_CONT_TARGET_IO
- XPT_SCSI_IO
- bus_dmamap_load_mbuf( dmat, map, mbuf, callback2, callback_arg, flags)
-
これは、DMA 転送のための mbuf チェーンをマップする
bus_dmamap_load() の変形です。また、
bus_size_t 引数は、mbuf チェーンのパケットヘッダ長を含んで、コールバックルーチンに渡されます。
BUS_DMA_NOWAIT フラグを意味し、したがって、コールバックの延期は、起こりません。
mbuf チェーンは、カーネル仮想アドレス空間にあると仮定されます。
bus_dmamap_load() のためにリストされたエラー値の他に、 mbuf チェーンのサイズが DMA タグの最大の制限を超えるなら、 EINVAL が返されます。
- bus_dmamap_load_mbuf_sg( dmat, map, mbuf, segs, nsegs, flags)
- 直ちにコールバック関数を呼び出さないで返ることを除いて、 bus_dmamap_load_mbuf() と同様です。それを効率的に提供します。散乱/収集 (scatter/gather) セグメント配列 segs は、呼び出し側によって提供されて、直接関数によって書き込まれます。 nsegs 引数は、セグメントの数が書き込まれた状態で返されます。 bus_dmamap_load_mbuf() と同じエラーを返します。
- bus_dmamap_load_uio( dmat, map, uio, callback2, callback_arg, flags)
-
これは、DMA 転送のための
uio によって指されたバッファをマップする
bus_dmamap_load() の変形です。また、
uio のサイズ、すなわち、
uio->uio_resid を含む、
bus_size_t 引数は、コールバックルーチンに渡されます。
BUS_DMA_NOWAIT フラグを意味し、したがって、コールバックの延期は、起こりません。
bus_dmamap_load() と同じエラーを返します。
uio->uio_segflg が UIO_USERSPACE であるなら、バッファ、 uio は、 uio->uio_td->td_proc のアドレス空間にあると仮定されます。ユーザ空間のメモリは、マップロード操作を試みる前に、コア中にあってワイヤードでなければなりません。ページは、 vslock(9) を使用してロックされるかもしれません。
- bus_dmamap_unload( dmat, map)
-
DMA マップをアンロードします。引数は、次の通りです:
- dmat
- DMA タグは、 map に割り付けるために使用します。
- map
- アンロードされる DMA マップ。
bus_dmamap_unload() は、DMA バッファの少しの暗黙の同期も実行しません。これは、マップをアンロードする前に、 bus_dmamap_sync() への呼び出しによって明らかに行われなければなりません。
- bus_dmamap_sync( dmat, map, op)
-
そのマッピングによって参照される CPU の目に見えるメモリでデバイスの目に見えるマッピングの同期を実行します。引数は、次の通りです:
- dmat
- DMA タグは、 map に割り付けるために使用します。
- map
- 同期される DMA マッピング。
- op
- 実行する同期操作のタイプ。 op に関する受け付け可能な値の記述については、 bus_dmasync_op_t の定義を参照してください。
bus_dmamap_sync() 関数は、共有メモリへの CPU とデバイスのダイレクトメモリアクセス (DMA) が一貫性を持っているのを保証するために使用されるメソッドです。例えば、CPU は、デバイスが利用可能となっているバッファの内容をセットアップするために使用されるかもしれません。デバイスのメモリのマッピングを通してデータが目に見えるすることを保証するために、バッファがロードされなければなりません、そして、CPU がバッファを更新した後で、デバイスアクセスが開始される前に、 BUS_DMASYNC_PREWRITE の DMA 同期操作を実行しなければなりません。 CPU が後で再びこのバッファを変更するなら、付加デバイスアクセスの前に、別の BUS_DMASYNC_PREWRITE 同期操作を実行しなければなりません。逆に、デバイスが CPU によって読み込まれることになっているメモリを更新すると仮定します。この場合は、バッファがロードされなければならず、デバイスアクセスが開始される前に、 BUS_DMASYNC_PREREAD の DMA 同期操作を実行しなければなりません。 CPU は、いったん DMA 操作が完了すると、このメモリの更新の結果をわかることができるのみで、 BUS_DMASYNC_POSTREAD 同期操作が実行されます。
読み込み書き込み操作が先行されず、適切な同期操作が続くなら、振る舞いは、未定義です。
- bus_dmamem_alloc( dmat, **vaddr, flags, *mapp)
-
vaddr に返されたアドレスで KVA にマップされ、
mapp を通して返された新たに作成された
bus_dmamap_t に取り外せないようにロードされる、メモリを割り付けます。引数は、次の通りです:
- dmat
- DMA マッピングの制約を記述する DMA タグ。
- vaddr
- 割り付けられた領域の返された KVA マッピングを保持するポインタへのポインタ。
- flags
-
フラグは、次の通りに定義されます:
- BUS_DMA_WAITOK
- ルーチンは、安全にリソースをウェート (スリープ) することができます。
- BUS_DMA_NOWAIT
- ルーチンは、リソースを待つことができません。リソースが利用可能でないなら、 ENOMEM が返されます。
- BUS_DMA_COHERENT
- 論理的なやり方で、このメモリをマップすることを試みます。このフラグの説明について、上記の bus_dmamap_create() を参照してください。 bus_dmamem_alloc() に関して、 BUS_DMA_COHERENT フラグは、現在、arm と sparc64 で実装されています。
- BUS_DMA_ZERO
- 割り付けられたメモリがすべての 0 に設定されます。
- BUS_DMA_NOCACHE
- 割り付けられたメモリは、プロセッサキャッシュでキャッシュされません。すべてのメモリアクセスは、バス上に現れて、再順序付けしないで、実行されます。 bus_dmamem_alloc() に関して、 BUS_DMA_NOCACHE フラグは、現在、割り付けられた仮想アドレス範囲に設定される Strong Uncacheable PAT の結果となる、 amd64 と i386 で実装されています。
- mapp
- 結果の DMA マップが格納される bus_dmamap_t へのポインタ。
割り付けられるメモリのサイズは、 dmat のための bus_dma_tag_create() への呼び出しで指定されるような maxsize です。
bus_dmamem_alloc() の現在の実装は、ただ一つのセグメントとしてすべての要求を割り付けます。
初期ロード操作は、下記の bus_dmamem_free() で説明されるように、割り付けられたメモリのバスアドレスを取得するために必要で、メモリを解放する前にアンロード操作が必要です。マップは、この関数によって自動的に取り扱われ、明示的に割り付けるべきでなく、破壊するべきではありません。
明白なロードは、返されたマップによって参照されるメモリにアクセスするごとに必要ではありませんが、 bus_dmamap_sync() セクションで説明される同期要件は、まだ適用され、コヒーレントな (首尾一貫した) バスなしのアーキテクチャで移植性を達成するために使用されるべきです。
十分なメモリが操作を完了するために利用可能でないなら、 ENOMEM を返します。
- bus_dmamem_free( dmat, *vaddr, map)
-
以前に
bus_dmamem_alloc() によって割り付けられたメモリを解放します。すべてのマッピングは、無効にされます。引数は、次の通りです:
- dmat
- DMA タグ。
- vaddr
- メモリのカーネル仮想アドレス。
- map
- 無効にされる DMA マップ。
戻り値
無効の引数が上記の関数のいずれかに渡されるなら、振る舞いは、未定義です。与えられたトランザクションのために十分なリソースを割り付けることができないなら、 ENOMEM が返されます。タイプ void でないすべてのルーチンは、上で議論されたように成功で 0 を返すか、失敗でエラーコードを返します。すべての void ルーチンは、有効な引数が提供されるなら、成功します。
ロック
2 つのロックプロトコルは、 bus_dma によって使用されます。 1 番目は、それらを利用するアーキテクチャでバウンスバッファプールへのアクセスを同期するために使用されるプライベートなグローバルロックです。このロックは、 bus_dma の内部で使用されるのみである厳密なリーフロックであり、 API のクライアントに公開されません。2 番目のプロトコルは、タグに格納された様々なリソースを保護することを必要とします。ほとんどすべての bus_dma 操作は、タグを作成したドライバからの要求を通して行われるので、タグリソースを保護する最も効率的な方法は、ドライバが使用するロックを通して行われます。 bus_dma が、ドライバによって呼び出されることなく、それ自身で動作する場合には、タグで指定されていたロックプリミティブは、取得され、自動的に解放されます。この例は、 bus_dmamap_load() コールバック関数がドライバコンテキストの代わりに延期されたコンテキストから呼び出されるときです。これは、特定の bus_dma 関数が、タグで指定され保持された同じロックで常に呼び出されなければならないことを意味します。これらの関数は、次を含みます:
- bus_dmamap_load()
- bus_dmamap_load_bio()
- bus_dmamap_load_ccb()
- bus_dmamap_load_mbuf()
- bus_dmamap_load_mbuf_sg()
- bus_dmamap_load_uio()
- bus_dmamap_unload()
- bus_dmamap_sync()
この規則には、1 つの例外があります。ドライバが任意の保持されたロックなしで開始される間にこれらの関数のいくつを呼び出す共通の習慣です。この操作の間に異なったスレッドによってタグの起こり得る並列使用がないことの保証がある限り、これらの関数のためのロックを保持しないことは安全です。
特定の bus_dma 操作は、それらが内部のロックによって既に保護されているので、またはメモリまたはリソースの割り付けのためにスリープするかもしれないので、ドライバロックが保持されている状態で、呼び出されるべきではありません。任意のスリープ不可能なロックが保持されている状態で、次の関数を呼び出してはいけません:
- bus_dma_tag_create()
- bus_dmamap_create()
- bus_dmamem_alloc()
他のすべての関数は、ロックプロトコルを持ちません、したがって、任意のシステム、または保持されたドライバのロックのあるなしにかかわらず呼び出すことがきます。
関連項目
devclass(9), device(9), driver(9), rman(9), vslock(9)Jason R. Thorpe, A Machine-Independent DMA Framework for NetBSD, Proceedings of the Summer 1998 USENIX Technical Conference, USENIX Association, June 1998.
歴史
bus_dma インタフェースは、 NetBSD 1.3 ではじめて登場しました。bus_dma API は、CAM SCSI サブシステムでの使用のために NetBSD から導入されました。オリジナルの API への変更は、呼び出し側が少ないリソースにキューを作るのを許している間に各 bus_dmamap_t に格納された bus_dma_segment_t 配列ための必要性を取り除くために向けられます。
作者
bus_dma インタフェースは、Numerical Aerospace Simulation Facility, NASA Ames Research Center (NASA Ames 研究センタ) の によって設計されて実行されました。 bus_dma 設計に関する追加入力は、 , , , , と によって提供されました。FreeBSD の bus_dma インタフェースは、 , , , , , , , , と他の多くの人々の貢献から恩恵を受けています。
このマニュアルページは、
と によって書かれました。July 17, 2013 | FreeBSD |