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

印刷ビューの終了

更新: 2014 年 9 月
 
 

GLDv2 のエントリポイント

エントリポイントは、GLDv2 とのインタフェースとして設計されたデバイス固有ネットワークドライバによって実装される必要があります。

gld_mac_info(9S) 構造体は、デバイス固有ドライバと GLDv2 モジュール間の通信のためのメイン構造体です。gld (7D) のマニュアルページを参照してください。この構造体の一部の要素は、ここで説明するエントリポイントへの関数ポインタです。デバイス固有ドライバは、gld_register() を呼び出す前に、その attach(9E) ルーチンでこれらの関数ポインタを初期化する必要があります。

gldm_reset() エントリポイント

int prefix_reset(gld_mac_info_t *macinfo);

gldm_reset() は、ハードウェアを初期状態にリセットします。

gldm_start() エントリポイント

int prefix_start(gld_mac_info_t *macinfo);

gldm_start() は、デバイスによる割り込みの生成を有効にします。また gldm_start() は、gld_recv() を呼び出して受信データパケットを GLDv2 に配信できるようにドライバを準備します。

gldm_stop() エントリポイント

int prefix_stop(gld_mac_info_t *macinfo);

gldm_stop() は、デバイスによる割り込みの生成を無効にし、デバイスが gld_recv() を呼び出してデータパケットを GLDv2 に配信しないようにします。GLDv2 は、デバイスがこれ以上割り込みをかけないようにするために、gldm_stop() ルーチンを利用します。gldm_stop() による処理は失敗してはなりません。この関数は常に GLD_SUCCESS を返します。

gldm_set_mac_addr() エントリポイント

int prefix_set_mac_addr(gld_mac_info_t *macinfo, unsigned char *macaddr);

gldm_set_mac_addr() は、ハードウェアがデータの受信に使用する物理アドレスを設定します。この関数は、渡された MAC アドレス macaddr を介してデバイスをプログラミングできるようにします。要求にこたえるために十分なリソースが現在利用できない場合、gldm_set_mac_add() は GLD_NORESOURCES を返します。要求された関数がサポートされていない場合、gldm_set_mac_add() は GLD_NOTSUPPORTED を返す必要があります。

gldm_set_multicast() エントリポイント

int prefix_set_multicast(gld_mac_info_t *macinfo, 
     unsigned char *multicastaddr, int multiflag);

gldm_set_multicast() は、特定のマルチキャストアドレスのデバイスレベルでの受信を有効または無効にします。3 番目の引数 multiflagGLD_MULTI_ENABLE に設定した場合、gldm_set_multicast() はマルチキャストアドレス宛てのパケットを受信するようにインタフェースを設定します。gldm_set_multicast() は、2 番目の引数によって指示されたマルチキャストアドレスを使用します。multiflagGLD_MULTI_DISABLE に設定した場合、ドライバは指定されたマルチキャストアドレスの受信を無効にできます。

この関数は、GLDv2 でマルチキャストアドレス、グループアドレス、または機能アドレスの受信を有効または無効にしようとするたびに呼び出されます。GLDv2 は、デバイスがどのような方法でマルチキャストをサポートするのか、またどのような方法でこの関数を呼び出して特定のマルチキャストアドレスを有効または無効にするのかについて、何の想定も行いません。デバイスによっては、ハッシュアルゴリズムとビットマスクを使用して、マルチキャストアドレスの集合を有効にする場合があります。この手順は認められており、GLDv2 が余分なパケットをフィルタリングして除外します。1 つのアドレスを無効にするとデバイスレベルで複数のアドレスが無効になる可能性がある場合、デバイスドライバで必要な情報を保持するようにしてください。これによって、GLDv2 が有効にしたが無効にはしていないアドレスを無効にすることを防ぎます。

gldm_set_multicast() は、すでに有効になっている特定のマルチキャストアドレスを有効にするために呼び出されることはありません。同様に、現在有効になっていないアドレスを無効にするために gldm_set_multicast () が呼び出されることもありません。GLDv2 は同じマルチキャストアドレスに対する複数の要求を追跡します。GLDv2 がドライバのエントリポイントを呼び出すのは、特定のマルチキャストアドレスの有効化を求める最初の要求、または無効化を求める最後の要求が行われたときだけです。その時点でリソースが不足していて要求を満たすことができない場合、この関数は GLD_NORESOURCES を返します。要求された関数がサポートされていない場合、この関数は GLD_NOTSUPPORTED を返します。

gldm_set_promiscuous() エントリポイント

int prefix_set_promiscuous(gld_mac_info_t *macinfo, int promiscflag);

gldm_set_promiscuous() は、プロミスキュアス (promiscuous) モードを有効または無効にします。この関数は、GLDv2 がメディア上のすべてのパケットの受信を有効または無効にしようとするたびに呼び出されます。関数の対象範囲を、メディア上のマルチキャストパケットに限定することもできます。2 番目の引数 promiscflag の値を GLD_MAC_PROMISC_PHYS に設定すると、この関数は物理レベルのプロミスキュアス (promiscuous) モードを有効にします。物理レベルのプロミスキュアス (promiscuous) モードが有効になると、メディア上のすべてのパケットが受信されます。promiscflagGLD_MAC_PROMISC_MULTI に設定すると、すべてのマルチキャストパケットの受信が有効になります。promiscflagGLD_MAC_PROMISC_NONE に設定すると、プロミスキュアス (promiscuous) モードが無効になります。

プロミスキュアス (promiscuous) マルチキャストモードの場合、マルチキャスト限定のプロミスキュアス (promiscuous) モードを備えていないデバイス用のドライバでは、デバイスを物理プロミスキュアス (promiscuous) モードに設定する必要があります。これにより、すべてのマルチキャストパケットの受信が保証されます。この場合、ルーチンは GLD_SUCCESS を返します。GLDv2 ソフトウェアが余分なパケットをフィルタリングして除外します。その時点でリソースが不足していて要求を満たすことができない場合、この関数は GLD_NORESOURCES を返します。要求された関数がサポートされていない場合、gld_set_promiscuous() 関数は GLD_NOTSUPPORTED を返します。

上位互換性のために、gldm_set_promiscuous() ルーチンは、promiscflag の認識できない値をすべて GLD_MAC_PROMISC_PHYS として扱います。

gldm_send() エントリポイント

int prefix_send(gld_mac_info_t *macinfo, mblk_t *mp);

gldm_send() は、転送するパケットをデバイスのキューに入れます。このルーチンには、送信するパケットが格納された STREAMS メッセージを渡します。メッセージには複数のメッセージブロックが含まれる場合があります。send() ルーチンは、メッセージのすべてのメッセージブロックをたどって、送信パケット全体にアクセスする必要があります。長さが 0 のメッセージ継続ブロックがチェーンに含まれる場合に、そのブロックを認識してスキップするようにドライバを準備してください。またドライバでは、パケットが最大許容パケットサイズを超えないことをチェックしてください。ドライバは必要に応じて、最小許容パケットサイズにパケットをパディングする必要があります。送信ルーチンがパケットを正常に転送するか、またはキューに入れた場合、GLD_SUCCESS が返されます。

パケットの転送がただちに受け入れられなかった場合、送信ルーチンは GLD_NORESOURCES を返します。この場合、GLDv2 はあとで再試行します。gldm_send()GLD_NORESOURCES を返した場合、あとでリソースが利用可能になった時点でドライバは gld_sched() を呼び出す必要があります。この gld_sched() の呼び出しは、ドライバが以前に転送キューに入れることができなかったパケットを再試行するよう GLDv2 に通知します (ドライバの gldm_stop() ルーチンが呼び出されても、ドライバが gldm_send() ルーチンから GLD_NORESOURCES を返すまで、ドライバはこの義務を免除されます。ただし、gld_sched() を余分に呼び出しても、誤った動作になることはありません)。

ドライバの送信ルーチンが GLD_SUCCESS を返した場合、メッセージが不要になった時点でドライバはそのメッセージを解放する必要があります。ハードウェアが DMA を使用してデータを直接読み取る場合、ドライバはハードウェアが完全にデータを読み取るまでメッセージを解放してはなりません。この場合、ドライバは割り込みルーチンでメッセージを解放できます。ドライバは別の方法として、将来の送信操作の開始時にバッファーを再要求することもできます。送信ルーチンが GLD_SUCCESS 以外に何も返さない場合、ドライバはメッセージを解放してはいけません。ネットワークまたはリンクパートナーとの物理接続がないときに gldm_send() が呼び出された場合は、GLD_NOLINK を返します。

gldm_intr() エントリポイント

int prefix_intr(gld_mac_info_t *macinfo);

gldm_intr() は、デバイスが割り込みをかけた可能性があるときに呼び出されます。割り込みをほかのデバイスと共有している可能性があるので、ドライバはデバイスのステータスを調べ、実際に割り込みが発生したかどうかを判別する必要があります。ドライバが制御しているデバイスで割り込みが起きなかった場合、このルーチンは DDI_INTR_UNCLAIMED を返す必要があります。それ以外の場合は、割り込みを処理して DDI_INTR_CLAIMED を返す必要があります。パケットの正常な受信によって割り込みが発生した場合、このルーチンは受信パケットを M_DATA 型の STREAMS メッセージに格納し、メッセージを gld_recv() に渡します。

gld_recv() は、着信パケットをアップストリーム方向に、ネットワークプロトコルスタックの該当する次の層に渡します。gld_recv() を呼び出す前に、ルーチンは STREAMS メッセージの b_rptr および b_wptr メンバーを正しく設定する必要があります。

ドライバでは、gld_recv() の呼び出し中に mutex ロックまたはまたはその他のロックを保持しないようにしてください。特に、転送スレッドが使用する可能性のあるロックが、gld_recv() の呼び出し中に保持されていてはなりません。場合によっては、gld_recv() を呼び出す割り込みスレッドが発信パケットを送信し、結果的にドライバの gldm_send() ルーチンが呼び出されてしまうためです。gld_recv() の呼び出し時に gldm_intr() によって保持されている mutex を gldm_send() が取得しようとすると、mutex エントリの再帰性が原因でパニックが発生します。gld_recv() の呼び出しでドライバが保持する mutex をほかのドライバのエントリポイントが取得しようとすると、デッドロックに陥る可能性があります。

割り込みコードは、どのようなエラーの発生時にも統計情報カウンタを 1 増やします。このエラーには、受信データに必要なバッファーの割り当て失敗に加えて、CRC エラーやフレームエラーなどのハードウェア固有エラーが含まれています。

gldm_get_stats() エントリポイント

int prefix_get_stats(gld_mac_info_t *macinfo, struct gld_stats *stats);

gldm_get_stats() は、ハードウェア、ドライバ専用カウンタ、またはその両方から統計情報を収集し、stats で指し示された gld_stats(9S) 構造体を更新します。このルーチンは、統計情報要求を受けたときに GLDv2 によって呼び出されます。GLDv2 は統計情報要求に対する応答を作成する前に、gldm_get_stats() メカニズムを使用してデバイス依存の統計情報をドライバから取得します。定義された統計情報カウンタの詳細は、gld_stats (9S)gld(7D) 、および qreply(9F) のマニュアルページを参照してください。

gldm_ioctl() エントリポイント

int prefix_ioctl(gld_mac_info_t *macinfo, queue_t *q, mblk_t *mp);

gldm_ioctl() は、デバイス固有の ioctl コマンドを実装します。ドライバで ioctl 関数を実装しない場合、この要素は null として指定できます。ドライバはメッセージブロックを ioctl 応答メッセージに変換し、GLD_SUCCESS を返す前に qreply(9F) 関数を呼び出す必要があります。この関数は常に GLD_SUCCESS を返します。ドライバでは必要に応じて、qreply (9F) に渡すメッセージでエラーを報告してください。gldm_ioctl 要素が NULL として指定されている場合、GLDv2 は M_IOCNAK 型のメッセージを EINVAL エラーとともに返します。