Solaris 8 のソフトウェア開発 (追補)

エントリポイント

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

gld(7D) で記述されているように、デバイス固有のドライバと GLD モジュール間の通信に関するメインデータ構造は、gld_mac_info(9S) 構造体です。この構造体の一部の要素は、ここで説明するエントリポイントへの関数ポインタです。デバイス固有のドライバは、attach(9E) ルーチンで、これらの関数ポインタを初期化してから gld_register() を呼び出さなければなりません。


int prefix_reset(gld_mac_info_t * macinfo);

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


int prefix_start(gld_mac_info_t * macinfo);

gldm_start() により、デバイスは割り込みを発生させ、受信データパケットを GLD に配信する目的で、ドライバが gld_recv() を呼び出せるようにします。


int prefix_stop(gld_mac_info_t * macinfo);

gldm_stop() は、デバイスが割り込みを発生させることを不可にし、データパケットを GLD に配信する目的でドライバが gld_recv() を呼び出すことを止めさせます。GLD は gldm_stop() ルーチンによって、デバイスがこれ以上割り込みをかけなくなることを確実に保証しなければなりません。この関数は常に、GLD_SUCCESS を返します。


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

gldm_set_mac_addr() は、ハードウェアがデータの受信に使用する物理アドレスを設定します。この関数は、デバイスを渡された MAC アドレス macaddr にプログラムしなければなりません。現在利用できるリソースが不足していて要求を満たすことができない場合は、GLD_NORESOURCES を返します。要求された関数がサポートされていない場合は、GLD_NOTSUPPORTED を返します。


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

gldm_set_multicast() は、特定のマルチキャストアドレスのデバイスレベルでの受け付けを可能または不可能にします。3 番目の引数 multiflagGLD_MULTI_ENABLE に設定されている場合、この関数は 2 番目の引数によって示されたマルチキャストアドレスを持つパケットを受信するよう、インタフェースを設定します。multiflagGLD_MULTI_DISABLE に設定されている場合、ドライバは指定されたマルチキャストアドレスの受け付けを不可にすることが許可されます。

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

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


int prefix_set_promiscuous(gld_mac_info_t * macinfo, int promiscflag);

gldm_set_promiscuous() は、プロミスキュアスモードを有効または無効にします。この関数は、GLD がメディア上のすべてのパケットの受信、またはメディア上のすべてのマルチキャストパケットの受信を可能または不可能に設定するたびに呼び出されます。2 番目の引数 promiscflagGLD_PROMISC_PHYS の値に設定されている場合は、この関数は物理レベルのプロミスキュアスモードを有効にし、その結果、メディア上のすべてのパケットが受信されます。promiscflagGLD_PROMISC_MULTI に設定されている場合は、すべてのマルチキャストパケットの受信が可能になります。promiscflagGLD_PROMISC_NONE に設定されている場合は、プロミスキュアスモードが不可になります。

プロミスキュアスマルチキャストモードの要求の場合、マルチキャスト専用プロミスキュアスモードを備えていないデバイスのドライバは、デバイスを物理プロミスキュアスモードに設定して、すべてのマルチキャストパケットが受信されるようにしなければなりません。その場合、ルーチンは GLD_SUCCESS を返さねばなりません。GLD ソフトウェアが余分なパケットをフィルタリングして除外します。そのとき、利用できるリソースが不足していて要求を満たせない場合、GLD_NORESOURCES を返します。要求された関数がサポートされていない場合は、GLD_NOTSUPPORTED を返します。

上位互換性を維持するために、gldm_set_promiscuous() ルーチンは、promiscflag として認識できないすべての値を GLD_PROMISC_PHYS のように扱う必要があります。


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

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

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

ドライバの送信ルーチンが GLD_SUCCESS を返し、ドライバとハードウェアでそのメッセージがもう不要になったときに、メッセージを解放するのはドライバの役目です。送信ルーチンがデバイスにメッセージをコピーした場合、または専用バッファにコピーした場合は、コピー後に送信ルーチンでメッセージを解放できます。ハードウェアが DMA を使用して、メッセージデータブロックから直接データを読み取る場合は、ハードウェアによるデータの読み取りが完了するまで、ドライバはメッセージを解放してはなりません。この場合、ドライバは割り込みルーチンでメッセージを解放するか、または将来の送信動作の開始時にバッファ再請求動作でメッセージを解放するのが一般的です。送信ルーチンが GLD_SUCCESS 以外のものを返した場合、ドライバはメッセージを解放してはなりません。ネットワークまたはリンクパートナーとの間に物理接続が無いときに gldm_send() が呼び出された場合は、GLD_NOLINK を返します。


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() ルーチンが呼び出されてしまうことがあるためです。gldm_intr() ルーチンが gld_recv() を呼び出すときに保持していた相互排他ロックを、gldm_send() ルーチンが取得しようとした場合、相互排他エントリが繰り返されることになり、パニックに陥る可能性があります。

割り込みコードは、あらゆるエラーに関する統計カウンタを増分しなければなりません。このエラーには、受信データ用バッファの割り当てエラーをはじめ、CRC エラーやフレーミングエラーなどのハードウェア固有のエラーが含まれます。


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

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


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

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

戻り値

これまでに説明した戻り値および制限事項のほかに、一部の GLD エントリポイント関数によって戻される値があります。次のとおりです。

GLD_BADARG

関数が不適切な引数、たとえば、不良マルチキャストアドレス、不良 MAC アドレス、不良パケット、不良パケット長などを検出した場合

GLD_FAILURE

ハードウェア障害の場合

GLD_SUCCESS

成功した場合