gld_mac_info(9S) 構造体に対するポインタ。
有効な MAC アドレスが格納されたキャラクタ配列の先頭に対するポインタ。この配列は、gld_mac_info(9S) 構造体の gldm_addrlen 要素で、ドライバによって指定された長さになります。
マルチキャスト、グループ、または機能アドレスが格納されたキャラクタ配列の先頭に対するポインタ。この配列は、gld_mac_info(9S) 構造体の gldm_addrlen 要素で、ドライバによって指定された長さになります。
マルチキャストアドレスの受け付けを可能にするか不可能にするかを示すフラグ。この引数は、GLD_MULTI_ENABLE または GLD_MULTI_DISABLE として指定します。
有効になっているプロミスキュアスモードのタイプを示すフラグ。この引数は、GLD_MAC_PROMISC_PHYS、GLD_MAC_PROMISC_MULTI、または GLD_MAC_PROMISC_NONE として指定します。
gld_ioctl() は、実行する ioctl が格納されている STREAMS メッセージブロックへのポインタとして mp を使用します。gld_send() は、送信するパケットが格納されている STREAMS メッセージブロックへのポインタとして mp を使用します。gld_recv() は、受信パケットが格納されているメッセージブロックへのポインタとして mp を使用します。
統計カウンタの現在値が入る、gld_stats(9S) 構造体に対するポインタ。
ioctl への応答で使用される、queue(9S) 構造体に対するポインタ。
デバイスの dev_info 構造体に対するポインタ。
デバイスのインタフェース名
これらのエントリポイントは、GLD とのインタフェースとして設計されたデバイス固有のネットワークドライバによって実装される必要があります。
gld(7D) で記述されているように、デバイス固有のドライバと GLD モジュール間の通信に関するメインデータ構造は、gld_mac_info(9S) 構造体です。この構造体の一部の要素は、ここで説明するエントリポイントへの関数ポインタです。デバイス固有のドライバは、attach(9E) ルーチンで、これらの関数ポインタを初期化してから gld_register() を呼び出さなければなりません。
|
gldm_reset() は、ハードウェアを初期状態にリセットします。
|
gldm_start() により、デバイスは割り込みを発生させ、受信データパケットを GLD に配信する目的で、ドライバが gld_recv() を呼び出せるようにします。
|
gldm_stop() は、デバイスが割り込みを発生させることを不可にし、データパケットを GLD に配信する目的でドライバが gld_recv() を呼び出すことを止めさせます。GLD は gldm_stop() ルーチンによって、デバイスがこれ以上割り込みをかけなくなることを確実に保証しなければなりません。この関数は常に、GLD_SUCCESS を返します。
|
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 番目の引数 multiflag が GLD_MULTI_ENABLE に設定されている場合、この関数は 2 番目の引数によって示されたマルチキャストアドレスを持つパケットを受信するよう、インタフェースを設定します。multiflag が GLD_MULTI_DISABLE に設定されている場合、ドライバは指定されたマルチキャストアドレスの受け付けを不可にすることが許可されます。
この関数は、GLD がマルチキャスト、グループ、または機能アドレスの受け付けを可能または不可能に設定するたびに呼び出されます。GLD は、デバイスがどのような方法でマルチキャストをサポートするのか、どのような方法でこの関数を呼び出して特定のマルチキャストアドレスを有効または無効にするのかについて、何も想定を行いません。デバイスによっては、ハッシュアルゴリズムとビットマスクを使用して、マルチキャストアドレスの集合を有効にするものもあります。この手順は認められており、GLD が余分なパケットをフィルタリングして除外します。1 つのアドレスを無効にするとデバイスレベルで複数のアドレスが無効になる可能性がある場合、GLD が有効にしているアドレスを無効にしてしまうことがないように、必要な情報を保存するのはデバイスドライバ側の役目です。
gldm_set_multicast() は、すでに有効になっている特定のマルチキャストアドレスを有効にする、または現在有効になっていないアドレスを無効にする状況では呼び出されません。GLD は同じマルチキャストアドレスに対する複数の要求を追跡し、特定のマルチキャストアドレスを有効にすることを求める最初の要求、または無効にすることを求める最後の要求に限り、ドライバのエントリポイントを呼び出します。そのとき、利用できるリソースが不足していて要求を満たせない場合は、GLD は GLD_NORESOURCES を返します。要求された関数がサポートされていない場合は、GLD_NOTSUPPORTED を返します。
|
gldm_set_promiscuous() は、プロミスキュアスモードを有効または無効にします。この関数は、GLD がメディア上のすべてのパケットの受信、またはメディア上のすべてのマルチキャストパケットの受信を可能または不可能に設定するたびに呼び出されます。2 番目の引数 promiscflag が GLD_PROMISC_PHYS の値に設定されている場合は、この関数は物理レベルのプロミスキュアスモードを有効にし、その結果、メディア上のすべてのパケットが受信されます。promiscflag が GLD_PROMISC_MULTI に設定されている場合は、すべてのマルチキャストパケットの受信が可能になります。promiscflag が GLD_PROMISC_NONE に設定されている場合は、プロミスキュアスモードが不可になります。
プロミスキュアスマルチキャストモードの要求の場合、マルチキャスト専用プロミスキュアスモードを備えていないデバイスのドライバは、デバイスを物理プロミスキュアスモードに設定して、すべてのマルチキャストパケットが受信されるようにしなければなりません。その場合、ルーチンは GLD_SUCCESS を返さねばなりません。GLD ソフトウェアが余分なパケットをフィルタリングして除外します。そのとき、利用できるリソースが不足していて要求を満たせない場合、GLD_NORESOURCES を返します。要求された関数がサポートされていない場合は、GLD_NOTSUPPORTED を返します。
上位互換性を維持するために、gldm_set_promiscuous() ルーチンは、promiscflag として認識できないすべての値を GLD_PROMISC_PHYS のように扱う必要があります。
|
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 を返します。
|
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 エラーやフレーミングエラーなどのハードウェア固有のエラーが含まれます。
|
gldm_get_stats() は、ハードウェア、ドライバ専用カウンタ、またはその両方から統計情報を収集し、stats で指し示された gld_stats(9S) 構造体を更新します。このルーチンは、統計要求を受けた時に GLD によって呼び出され、GLD が統計要求に対する応答を作成する前に、ドライバからデバイスに依存する統計情報を得るためのメカニズムを提供します。定義されている統計カウンタの詳細は、gld_stats(9S) および gld(7D) のマニュアルページを参照してください。
|
gldm_ioctl() は、すべてのデバイス固有の ioctl コマンドを実装します。ドライバが ioctl 関数を全く実装しない場合、この要素は NULL として指定できます。メッセージブロックを ioctl 応答メッセージに変換し、GLD_SUCCESS を呼び出す前に greply(9F) 関数を呼び出すのは、ドライバの役目です。この関数は常に GLD_SUCCESS を返すべきです。ドライバに報告させる必要のあるエラーは、greply(9F) に渡すメッセージで返させる必要があります。gldm_ioctl 要素が NULL として指定されている場合、GLD は M_IOCNAK タイプのメッセージを EINVAL というエラーとともに返します。
これまでに説明した戻り値および制限事項のほかに、一部の GLD エントリポイント関数によって戻される値があります。次のとおりです。
関数が不適切な引数、たとえば、不良マルチキャストアドレス、不良 MAC アドレス、不良パケット、不良パケット長などを検出した場合
ハードウェア障害の場合
成功した場合
|
gld_mac_alloc() は、新しい gld_mac_info(9S) 構造体を割り当て、その構造体に対するポインタを返します。この構造体の GLD 専用の要素のなかには、gld_mac_alloc() を返す前に初期化されるものがありますが、他の要素はすべてゼロに初期化されます。デバイスドライバは、gld_mac_info(9S) に記述されているように、一部の構造体メンバーを初期化してから、mac_info ポインタを gld_register() に渡さなければなりません。
|
gld_mac_free() は、以前に gld_mac_alloc() によって割り当てられていた gld_mac_info(9S) 構造体を解放します。
|
gld_register() は、デバイスドライバの attach(9E) ルーチンから呼び出され、GLD ベースのデバイスドライバと GLD フレームワークを結びつけるために使用されます。デバイスドライバの attach(9E) ルーチンは、gld_register() を呼び出す前に、gld_mac_alloc() を最初に使用して gld_mac_info(9S) 構造体を割り当て、その構造体の要素のいくつかを初期化しなければなりません。詳細は、lgld_mac_info(9S) のマニュアルページを参照してください。gld_register() が正常に呼び出されると、次の動作が発生します。
デバイス固有のドライバを GLD システムに接続する
デバイス固有のドライバの専用データポインタが (ddi_set_driver_private(9F) を使用して) macinfo 構造体を指し示すように設定する
マイナーデバイスノードを作成する
DDI_SUCCESS を返す
gld_register() に渡すデバイスインタフェース名は、ファイルシステムに存在しているドライバモジュール名と完全に一致しなければなりません。
ドライバの attach(9E) ルーチンは、gld_register() が正常に完了した場合に DDI_SUCCESS を返す必要があります。gld_register() が DDI_SUCCESS を返さなかった場合、attach(9E) ルーチンは gld_register() を呼び出す前に割り当てたすべてのリソースの割り当てを解除し、さらに DDI_FAILURE を返さなければなりません。
|
gld_unregister() は、デバイスドライバの detach(9E) 関数によって呼び出され、成功した場合は次の作業を実行します。
デバイスの割り込みが中止されたことを確認し、必要に応じてドライバの gldm_stop() ルーチンを呼び出す
マイナーデバイスノードを削除する
GLD システムとデバイス固有のドライバ間のリンクを切断する
DDI_SUCCESS を返す
gld_unregister() が DDI_SUCCESS を返した場合、detach(9E) ルーチンは attach(9E) ルーチンで割り当てられたすべてのデータ構造体を割り当て解除し、gld_mac_free() を使用して、macinfo 構造を割り当て解除し、DDI_SUCCESS を返します。gld_unregister() が DDI_SUCCESS を返さなかった場合、ドライバの detach(9E) ルーチンはデバイスを動作状態にしたまま、DDI_FAILURE を返さなければなりません。
|
gld_recv() は、ドライバの割り込みハンドラによって呼び出され、受信したパケットをアップストリームに渡します。ドライバは raw パケットを格納した STREAMS M_DATA メッセージを作成して渡さなければなりません。gld_recv() がパケットのコピーを受け取るべき STREAMS キュー (あれば) を判別し、必要に応じてコピーします。さらに、必要であれば DL_UNITDATA_IND メッセージをフォーマットして、データを該当するすべての STREAMS に渡します。
ドライバは、gld_recv() の呼び出し時に、相互排他 (mutex) ロックまたは他のロックを保持していないようにしなければなりません。特に、送信スレッドが使用するロックは、gld_recv() の呼び出し時には保持できません。場合によっては、gld_recv() を呼び出す割り込みスレッドが、発信パケットの送信を含めた処理を実行してしまい、その結果、ドライバの gldm_send() ルーチンが呼び出されることがあるためです。gldm_intr() ルーチンが gld_recv() を呼び出すときに保持していた相互排他ロックを、gldm_send() ルーチンが取得しようとした場合、相互排他エントリが繰り返されることになり、パニックになる可能性があります。
|
gld_sched() は、据え置かれていた発信パケットを再スケジューリングするために、デバイスドライバによって呼び出されます。ドライバの gldm_send() ルーチンが GLD_NORESOURCES を返すたびに、ドライバは後で gld_sched() を呼び出して、以前送信できなかったパケットについて再試行するように、GLD フレームワークに通知しなければなりません。gld_sched() は、リソースが利用可能になった時点で、できるかぎり迅速に呼び出され、GLD がドライバの gldm_send() ルーチンに対する発信パケットの受け渡しを、タイミングよく再開できるようにしなければなりません (ドライバの gldm_stop() ルーチンが呼び出されても、gldm_send() ルーチンから再び GLD_NORESOURCES が返されるまで、ドライバはこの義務を免除されます。ただし、gld_sched() を余分に呼び出しても、誤った動作になることはありません)。
|
gld_intr() は、GLD のメインの割り込みハンドラです。通常、デバイスドライバの ddi_add_intr(9F) 呼び出しで、割り込みルーチンとして指定します。割り込みハンドラに対する引数 (ddi_add_intr(9F) 呼び出しに int_handler_arg として指定) は、gld_mac_info(9S) 構造体へのポインタでなければなりません。gld_intr() は、該当する場合、デバイスドライバの gldm_intr() 関数を呼び出し、そのポインタを gld_mac_info(9S) 構造体に渡します。しかし、ドライバが上位レベルの割り込みを使用する場合は、独自の上位割り込みハンドラを提供し、その中からソフト割り込みを起動しなければなりません。この場合、gld_intr() は、ddi_add_softintr() 呼び出しにソフト割り込みハンドラとして指定できます。gld_intr() は、割り込みハンドラに適した値を返します。