JavaScript is required to for searching.
ナビゲーションリンクをスキップ
印刷ビューの終了
デバイスドライバの記述     Oracle Solaris 11.1 Information Library (日本語)
このドキュメントの評価
search filter icon
search icon

ドキュメントの情報

はじめに

パート I Oracle Solaris プラットフォーム用デバイスドライバの設計

1.  Oracle Solaris デバイスドライバの概要

2.  Oracle Solaris カーネルとデバイスツリー

3.  マルチスレッド

4.  プロパティー

5.  イベントの管理とタスクのキュー

6.  ドライバの自動構成

7.  デバイスアクセス: プログラム式入出力

8.  割り込みハンドラ

9.  ダイレクトメモリーアクセス (DMA)

10.  デバイスメモリーおよびカーネルメモリーのマッピング

11.  デバイスコンテキスト管理

12.  電源管理

13.  Oracle Solaris ドライバの強化

14.  階層化ドライバインタフェース (LDI)

パート II 特定の種類のデバイスドライバの設計

15.  文字デバイスのドライバ

16.  ブロックデバイスのドライバ

17.  SCSI ターゲットドライバ

18.  SCSI ホストバスアダプタドライバ

19.  ネットワークデバイスのドライバ

20.  USB ドライバ

Oracle Solaris 環境での USB

USBA 2.0 フレームワーク

USB クライアントドライバ

クライアントドライバのバインド

USB デバイスがシステムからどのように見えるか

USB デバイスと Oracle Solaris デバイスツリー

互換デバイス名

複数のインタフェースを備えたデバイス

インタフェース関連付け記述子を含むデバイス

デバイスドライバのバインディングのチェック

基本的なデバイスアクセス

クライアントドライバが接続される前

記述子ツリー

デバイスアクセスを取得するためのドライバの登録

デバイス通信

USB エンドポイント

デフォルトパイプ

パイプの状態

パイプのオープン

パイプのクローズ

データ転送

同期および非同期転送とコールバック

要求

パイプのフラッシュ

デバイス状態管理

USB デバイスのホットプラグ

ホットプラグコールバック

電源を入れたまま挿入

電源を入れたまま取り外し

電源を入れたまま再挿入

電源管理

デバイス電源管理

システム電源管理

直列化

ユーティリティー関数

デバイス構成機能

インタフェース番号の取得

デバイス全体の管理

複数の構成を持つデバイス

代替設定の変更または取得

その他のユーティリティー関数

文字列記述子の取得

パイプの非公開データ機能

USB 状態のクリア

デバイス、インタフェース、エンドポイントの各ステータスの取得

デバイスのバスアドレスの取得

サンプル USB デバイスドライバ

21.  SR-IOV ドライバ

パート III デバイスドライバの構築

22.  ドライバのコンパイル、ロード、パッケージ化、およびテスト

23.  デバイスドライバのデバッグ、テスト、およびチューニング

24.  推奨されるコーティング方法

パート IV 付録

A.  ハードウェアの概要

B.  Oracle Solaris DDI/DKI サービスのサマリー

C.  64 ビットデバイスドライバの準備

D.  コンソールフレームバッファードライバ

E.  pci.conf ファイル

索引

ドキュメントの品質向上のためのご意見をください
簡潔すぎた
読みづらかった、または難し過ぎた
重要な情報が欠けていた
内容が間違っていた
翻訳版が必要
その他
Your rating has been updated
貴重なご意見を有り難うございました!

あなたの貴重なご意見はより良いドキュメント作成の手助けとなります 内容の品質向上と追加コメントのためのアンケートに参加されますか?

デバイス通信

USB デバイスは、パイプと呼ばれる通信チャネル経由で要求を渡すことにより動作します。要求を送信するには、まずパイプをオープンする必要があります。パイプのフラッシュ、クエリー、およびクローズも行えます。このセクションでは、パイプ、データ転送とコールバック、およびデータ要求について説明します。

USB エンドポイント

4 種類の USB エンドポイントと通信を行う 4 種類のパイプを次に示します。

これらのエンドポイントに対応する転送タイプの詳細については、USB 2.0 仕様書の第 5 章を参照するか、「要求」を参照してください。

デフォルトパイプ

各 USB デバイスは、デフォルトエンドポイントと呼ばれる特殊な制御エンドポイントを持ちます。その通信チャネルはデフォルトパイプと呼ばれます。すべてではないにしろ、ほとんどのデバイス設定がこのパイプ経由で行われます。多くの USB デバイスは、自身の唯一の制御パイプとしてこのパイプを持ちます。

usb_get_dev_data(9F) 関数は、デフォルト制御パイプをクライアントドライバに提供します。このパイプは、ほかのパイプを開く前に必要とされるどのような特殊な設定にも対応できるよう、事前に開かれています。このデフォルト制御パイプは次の点で特殊です。

その他の制御パイプを含むほかのパイプは、明示的に開く必要があり、排他的にしか開くことができません。

パイプの状態

パイプの状態は次のいずれかになります。

パイプの状態を取得するには、usb_pipe_get_state(9F) 関数を呼び出します。

パイプのオープン

パイプを開くには、その開くパイプに対応するエンドポイント記述子を usb_pipe_open(9F) 関数に渡します。記述子ツリーからエンドポイント記述子を取得するには、usb_get_dev_data(9F) および usb_lookup_ep_data(9F) 関数を使用します。usb_pipe_open(9F) 関数はパイプへのハンドルを返します。

パイプを開くときにパイプポリシーを指定する必要があります。パイプポリシーには、このパイプで必要になると予想される、独立したスレッドを必要とする同時非同期処理の数が含まれています。予想されるスレッド数は、コールバック中に発生する可能性のある並列処理の数です。この予想値は 2 以上である必要があります。パイプポリシーの詳細については、usb_pipe_open(9F) のマニュアルページを参照してください。

パイプのクローズ

ドライバは、usb_pipe_close(9F) 関数を使用してデフォルトパイプ以外のパイプを閉じる必要があります。usb_pipe_close(9F) 関数は、パイプ内の残りの要求がすべて完了するまで待ちます。次にこの関数は、それらの要求のすべてのコールバックが完了するまで 1 秒間待ちます。

データ転送

どのパイプタイプの場合も、プログラミングモデルは次のようになります。

  1. 要求を割り当てます。

  2. いずれかのパイプ転送関数を使用して要求を送信します。usb_pipe_bulk_xfer(9F)usb_pipe_ctrl_xfer(9F)usb_pipe_intr_xfer(9F)、および usb_pipe_isoc_xfer(9F) のマニュアルページを参照してください。

  3. 完了通知が届くまで待ちます。

  4. 要求を解放します。

要求の詳細については、「要求」を参照してください。次の各セクションでは、さまざまな要求タイプの機能について説明します。

同期および非同期転送とコールバック

転送は同期型と非同期型のいずれかになります。同期転送は、転送が完了するまでブロックします。非同期転送では、転送完了時にクライアントドライバへのコールバックが発生します。flags 引数に USB_FLAGS_SLEEP フラグを設定して転送関数を呼び出した場合、その大部分は同期型になります。

ポーリングやアイソクロナス転送といった継続的な転送を同期型にすることはできません。継続的な転送向けの転送関数を呼び出すときに USB_FLAGS_SLEEP フラグを設定した場合、転送が始まる前に、リソースに対して待機するためだけに呼び出しがブロックされます。

同期転送は、設定がもっとも単純な転送です。これは、同期転送ではコールバック関数が一切必要ないからです。同期転送関数は、転送が完了するまでブロックするにもかかわらず、転送開始ステータスを返します。転送が完了すると、要求の完了理由フィールドとコールバックフラグフィールドに、転送ステータスに関する追加情報が表示されます。完了理由フィールドとコールバックフラグフィールドについては後述します。

flags 引数に USB_FLAGS_SLEEP フラグを指定しなかった場合、その転送処理は非同期型になります。この規則の例外は、アイソクロナス転送です。非同期転送処理は、転送を設定して開始したあと、転送が完了する前に戻ります。非同期転送処理は転送開始ステータスを返します。クライアントドライバは、コールバックハンドラ経由で転送完了ステータスを受け取ります。

コールバックハンドラとは、非同期転送の完了時に呼び出される関数のことです。非同期転送を設定する際には必ずコールバックを指定してください。コールバックハンドラには、正常終了ハンドラと例外ハンドラの 2 種類があります。このどちらの場合にも同じハンドラが呼び出されるように指定することもできます。

完了ハンドラと例外ハンドラはどちらも、転送の要求を引数として受け取ります。例外ハンドラは、要求内の完了理由とコールバックステータスに基づいて何が起こったのかを調べます。完了理由 (usb_cr_t) は、元のトランザクションがどのように完了したのかを示します。たとえば、完了理由 USB_CR_TIMEOUT は、転送がタイムアウトしたことを示します。別の例として、USB デバイスが使用中に削除された場合、クライアントドライバは自身の未処理の要求で、USB_CR_DEV_NOT_RESP を完了理由として受け取ります。コールバックステータス (usb_cb_flags_t) は、状況に対処するために USBA フレームワークが何を行ったのかを示します。たとえば、コールバックステータス USB_CB_STALL_CLEARED は、USBA フレームワークが機能ストールステータスをクリアしたことを示します。完了理由の詳細については、usb_completion_reason(9S) のマニュアルページを参照してください。コールバックステータスフラグの詳細については、usb_callback_flags(9S) のマニュアルページを参照してください。

コールバックのコンテキストと要求が実行されるパイプのポリシーによって、コールバック内で行える処理が制限されます。

要求

このセクションでは要求構造体、および各種の要求の割り当てと割り当て解除について説明します。

要求の割り当てと割り当て解除

要求は、初期化された要求構造体として実装されます。各エンドポイントタイプはそれぞれ異なるタイプの要求を受け取ります。要求タイプごとに異なる要求構造体型が用意されています。次の表に、各要求タイプの構造体型を示します。この表では、各構造体型の割り当てや解放に使用する関数の一覧も示しています。

表 20-1 要求の初期化

パイプまたはエンドポイントのタイプ
要求構造体
要求構造体割り当て関数
要求構造体解放関数
制御
usb_ctrl_req_t (usb_ctrl_request(9S) のマニュアルページを参照)
一括
usb_bulk_req_t (usb_bulk_request(9S) のマニュアルページを参照)
割り込み
usb_intr_req_t (usb_intr_request(9S) のマニュアルページを参照)
アイソクロナス
usb_isoc_req_t (usb_isoc_request(9S) のマニュアルページを参照)

次の表は、各要求タイプで使用可能な転送関数の一覧です。

表 20-2 要求転送の設定

パイプまたはエンドポイントのタイプ
転送関数
制御
一括
割り込み
アイソクロナス

要求の割り当てと割り当て解除を行う際には、次の手順に従います。

  1. 適切な割り当て関数を使用して、必要な要求タイプの要求構造体を割り当てます。要求構造体割り当て関数のマニュアルページについては、表 20-1 を参照してください。

  2. 構造体内で必要なフィールドをすべて初期化します。詳細については、「要求の機能とフィールド」または対応する要求構造体のマニュアルページを参照してください。要求構造体のマニュアルページについては、表 20-1 を参照してください。

  3. データ転送が完了したら、適切な解放関数を使用して要求構造体を解放します。要求構造体解放関数のマニュアルページについては、表 20-1 を参照してください。

要求の機能とフィールド

ドライバが STREAMS 型、文字型、ブロック型のいずれであっても、データが画一的に処理されるように、すべての要求のデータがメッセージブロックとして渡されます。メッセージブロック型 mblk_t については、mblk(9S) のマニュアルページを参照してください。DDI には、メッセージブロックを操作するためのルーチンがいくつか用意されています。たとえば、allocb(9F)freemsg(9F) などがあります。メッセージブロックを操作するためのその他のルーチンについて学ぶには、allocb(9F) および freemsg(9F) のマニュアルページの「関連項目」セクションを参照してください。また、『STREAMS Programming Guide』も参照してください。

すべての転送タイプに含まれる要求フィールドを次に示します。各フィールド名の xxxx は、ctrlbulkintrisoc のいずれかの値になります。

xxxx_client_private

このフィールドの値は、クライアントドライバで要求と一緒に渡される内部データ用のポインタになります。デバイスにデータを転送するためにこのポインタが使用されることはありません。

xxxx_attributes

このフィールドの値は、一連の転送属性になります。このフィールドはすべての要求構造体に共通しますが、その初期化方法は転送タイプごとに若干異なります。詳細については、対応する要求構造体のマニュアルページを参照してください。これらのマニュアルページについては、表 20-1 を参照してください。また、usb_request_attributes(9S) のマニュアルページも参照してください。

xxxx_cb

このフィールドの値は、転送が正常終了した場合のコールバック関数になります。この関数は、非同期転送がエラーなしで完了した場合に呼び出されます。

xxxx_exc_cb

このフィールドの値は、エラー処理用のコールバック関数になります。この関数が呼び出されるのは、非同期転送でエラーが発生した場合だけです。

xxxx_completion_reason

このフィールドには転送自体の完了ステータスが保持されます。エラーが発生した場合にこのフィールドを見れば、どのような問題が発生したのかがわかります。詳細については、usb_completion_reason(9S) のマニュアルページを参照してください。このフィールドは USBA 2.0 フレームワーク によって更新されます。

xxxx_cb_flags

このフィールドには、USBA 2.0 フレームワーク がコールバックハンドラを呼び出す前に行なった復旧処理のリストが含まれています。USB_CB_INTR_CONTEXT フラグは、コールバックが割り込みコンテキストで実行されているかどうかを示します。詳細については、usb_callback_flags(9S) のマニュアルページを参照してください。このフィールドは USBA 2.0 フレームワーク によって更新されます。

次の各セクションでは、4 つの転送タイプでそれぞれ異なる要求フィールドについて説明します。これらのセクションでは、それらの構造体フィールドを初期化する方法について説明します。また、属性やパラメータのさまざまな組み合わせに関する制限についてもこれらのセクションで説明します。

制御要求

制御パイプ経由でメッセージ転送を開始するには、制御要求を使用します。後述するように、転送は手動で設定できます。また、usb_pipe_ctrl_xfer_wait(9F) ラッパー関数を使用して同期転送を設定および送信することもできます。

クライアントドライバは、USB 2.0 仕様書に記載されているように、ctrl_bmRequestTypectrl_bRequestctrl_wValuectrl_wIndexctrl_wLength の各フィールドを初期化する必要があります。

要求の ctrl_data フィールドは、データバッファーを指すように初期化する必要があります。usb_alloc_ctrl_req(9F) 関数は、バッファーの len に正の値が渡された場合、このフィールドを初期化します。もちろん、アウトバウンド転送ではこのバッファーを必ず初期化する必要があります。いずれにしても、クライアントドライバは、転送完了時に要求を解放する必要があります。

複数の制御要求をキューに登録できます。キューに登録する要求として、同期要求と非同期要求を組み合わせてもかまいません。

ctrl_timeout フィールドは、要求が処理されまでの最大待機時間を定義します。ただし、キューでの待機時間は含めません。このフィールドは同期要求と非同期要求の両方に適用されます。 ctrl_timeout フィールドは秒単位で指定します。

ctrl_exc_cb フィールドには、例外の発生時に呼び出す関数のアドレスを指定します。この例外ハンドラの引数については、usb_ctrl_request(9S) のマニュアルページを参照してください。例外ハンドラの第 2 引数は、usb_ctrl_req_t 構造体です。要求構造体を引数として渡せば、例外ハンドラから要求の ctrl_completion_reason および ctrl_cb_flags フィールドをチェックし、最適な復旧処理を決定することが可能となります。

USB_ATTRS_ONE_XFER および USB_ATTRS_ISOC_* フラグは、すべての制御要求で無効な属性です。USB_ATTRS_SHORT_XFER_OK フラグは、ホスト宛ての要求でのみ有効です。

一括要求

処理時間の要件が高くないデータを送信するには、一括要求を使用します。バス全体の負荷によっては、一括要求が完了するまでに数 USB フレームかかる可能性があります。

すべての要求は、初期化済みのメッセージブロックを受け取る必要があります。mblk_t メッセージブロック型の説明については、mblk(9S) のマニュアルページを参照してください。このメッセージブロックは、転送の向きに応じてデータ提供とデータ格納のいずれかを行います。詳細については、usb_bulk_request(9S) のマニュアルページを参照してください。

USB_ATTRS_ONE_XFER および USB_ATTRS_ISOC_* フラグは、すべての一括要求で無効な属性です。USB_ATTRS_SHORT_XFER_OK フラグは、ホスト宛ての要求でのみ有効です。

usb_pipe_get_max_bulk_transfer_size(9F) 関数は、要求当たりの最大バイト数を指定します。取得した値は、クライアントドライバの minphys(9F) ルーチンで使用される最大値として指定できます。

複数の一括要求をキューに登録できます。

割り込み要求

割り込み要求は通常、定期的なインバウンドデータ用です。割り込み要求は、定期的にデバイスにポーリングしてデータの有無を確認します。ただし、USBA 2.0 フレームワーク では、1 回かぎりのインバウンド割り込みデータ要求やアウトバウンド割り込みデータ要求がサポートされています。USB 割り込み転送機能の適時性と再試行は、どの割り込み要求でも利用できます。

USB_ATTRS_ISOC_* フラグは、すべての割り込み要求で無効な属性です。USB_ATTRS_SHORT_XFER_OK および USB_ATTRS_ONE_XFER フラグは、ホスト宛ての要求でのみ有効です。

1 回かぎりのポーリングは必ず同期割り込み転送として実行されます。要求で USB_ATTRS_ONE_XFER 属性を指定すると、1 回かぎりのポーリングになります。

定期的なポーリングは、非同期割り込み転送として開始されます。元の割り込み要求を usb_pipe_intr_xfer(9F) に渡します。ポーリング中に返す新しいデータが見つかると、新しい usb_intr_req_t 構造体が元の要求から複製され、初期化済みのデータブロックが設定されます。要求を割り当てる際には、usb_alloc_intr_req(9F) 関数の len 引数にゼロを指定します。len 引数をゼロにするのは、USBA 2.0 フレームワーク がコールバックごとに新しい要求の割り当てやデータ設定を行うからです。要求構造体の割り当て後、その intr_len フィールドを設定することで、ポーリングごとにフレームワークが割り当てるバイト数を指定します。intr_len バイトを超えるデータは返されません。

クライアントドライバは、受け取った各要求を解放する必要があります。メッセージブロックをアップストリームに送信する場合、送信を行う前にメッセージブロックを要求から切り離します。メッセージブロックを要求から切り離すには、要求のデータポインタを NULL に設定します。要求のデータポインタを NULL に設定すると、要求が割り当て解除されるときに、メッセージブロックが解放されるのを防ぐことができます。

定期的なポーリングを取り消すには、usb_pipe_stop_intr_polling(9F) 関数を呼び出します。ポーリングを停止したりパイプを閉じたりすると、例外コールバック経由で元の要求構造体が返されます。この返される要求構造体の完了理由には、USB_CR_STOPPED_POLLING が設定されます。

ポーリングがすでに進行中である場合にポーリングを開始しないでください。usb_pipe_stop_intr_polling(9F) の呼び出しの進行中にポーリングを開始しないでください。

アイソクロナス要求

アイソクロナス要求は、一定速度の時間重視のストリーミングデータ用です。エラー時の再試行は行われません。アイソクロナス要求には次の要求固有フィールドが含まれています。

isoc_frame_no

転送全体を特定のフレーム番号から始める必要がある場合に、このフィールドを指定します。このフィールドの値は、現在のフレーム番号よりも大きい必要があります。現在のフレーム番号を取得するには、usb_get_current_frame_number(9F) を使用します。現在のフレーム番号は刻々変化します。低速バスやフルスピードバスでは、現在のフレームは 1 ミリ秒ごとに更新されます。高速バスでは、現在のフレームは 0.125 ミリ秒ごとに更新されます。isoc_frame_no フィールドが認識されるように、USB_ATTR_ISOC_START_FRAME 属性を設定します。

このフレーム番号フィールドを無視してできるだけすぐに開始するには、USB_ATTR_ISOC_XFER_ASAP フラグを設定します。

isoc_pkts_count

このフィールドは、リクエスト内のパケット数です。この値は、usb_get_max_pkts_per_isoc_request(9F) 関数から返される値と isoc_pkt_descr 配列 (後述の説明を参照) のサイズによって制限されます。このリクエストで転送可能なバイト数は、この isoc_pkts_count 値とエンドポイントの wMaxPacketSize 値の積に等しくなります。

isoc_pkts_length

このフィールドは、要求のすべてのパケットの長さを合計したものになります。この値はイニシエータによって設定されます。この値はゼロに設定して、isoc_pkt_descr リストの isoc_pkts_length の合計が自動的に使用され、この要素にチェックが適用されないようにしてください。

isoc_error_count

このフィールドは、エラーが発生して完了したパケットの数です。この値は USBA 2.0 フレームワーク によって設定されます。

isoc_pkt_descr

このフィールドは、各パケットのデータ転送量を定義したパケット記述子の配列を指します。送信要求の場合、この値は処理対象のサブ要求の非公開キューを定義します。受信要求の場合、この値は、データがどのように分割されて到着するかを記述します。送信要求の場合、クライアントドライバがこれらの記述子を割り当てます。受信要求の場合、フレームワークがこれらの記述子の割り当てと初期化を行います。この配列の各記述子にはフレームワークによって初期化されたフィールドが含まれており、それらのフィールドには、実際に転送されたバイト数と転送ステータスが保持されています。詳細については、usb_isoc_request(9S) のマニュアルページを参照してください。

すべての要求は、初期化済みのメッセージブロックを受け取る必要があります。このメッセージブロックはデータ提供とデータ格納のいずれかを行います。mblk_t メッセージブロック型の説明については、mblk(9S) のマニュアルページを参照してください。

USB_ATTR_ONE_XFER フラグは不正な属性です。システムが使用可能なパケット経由でデータ量をどのように変化させるかを決定するからです。USB_ATTR_SHORT_XFER_OK フラグは、ホスト宛てのデータでのみ有効です。

usb_pipe_isoc_xfer(9F) 関数は、USB_FLAGS_SLEEP フラグの設定の有無にかかわらず、すべてのアイソクロナス転送を非同期にします。アイソクロナス入力要求では必ずポーリングが開始されます。

定期的なポーリングを取り消すには、usb_pipe_stop_isoc_polling(9F) 関数を呼び出します。ポーリングを停止したりパイプを閉じたりすると、例外コールバック経由で元の要求構造体が返されます。この返される要求構造体の完了理由には、USB_CR_STOPPED_POLLING が設定されます。

ポーリングは、次のいずれかのイベントが発生するまで継続されます。

パイプのフラッシュ

エラー発生後にパイプをクリーンアップする必要に迫られたり、パイプが空になるまで待機したりする可能性があります。パイプのフラッシュやクリアを行うには、次のいずれかの方法を使用します。