GLDv3 は、MAC_PLUGIN_IDENT_ETHER タイプのプラグインに登録するドライバ用のドライバ API を定義します。
GLDv3 デバイスドライバは、次の手順を実行して MAC 層に登録する必要があります。
sys/mac_ether.h、sys/mac_provider.h の 2 つの MAC ヘッダーファイルをインクルードします。その他の MAC 関連ヘッダーファイルはドライバにインクルードしないでください。
mac_callbacks 構造体を生成します。
mac_init_ops() 関数をその _init() エントリポイントで呼び出します。
mac_alloc() 関数をその attach() エントリポイントで呼び出し、mac_register 構造体を割り当てます。
mac_register 構造体を生成し、mac_register() 関数をその attach() エントリポイントで呼び出します。
mac_unregister() 関数をその detach() エントリポイントで呼び出します。
mac_fini_ops() 関数をその _fini() エントリポイントで呼び出します。
misc/mac への依存性とリンクします。
# ld -N"misc/mac" xx.o -o xx
GLDv3 インタフェースには、MAC 層への登録中に通知されるドライバエントリポイントと、ドライバによって呼び出される MAC エントリポイントが含まれています。
void mac_init_ops(struct dev_ops *ops, const char *name);
GLDv3 デバイスドライバは mod_install(9F) を呼び出す前に、mac_init_ops(9F) 関数をその _init(9E) エントリポイントで呼び出す必要があります。
void mac_fini_ops(struct dev_ops *ops);
GLDv3 デバイスドライバは mod_remove(9F) を呼び出したあとに、mac_fini_ops(9F) 関数をその _fini(9E) エントリポイントで呼び出す必要があります。
使用例 19-1 mac_init_ops() および mac_fini_ops() 関数int _init(void) { int rv; mac_init_ops(&xx_devops, "xx"); if ((rv = mod_install(&xx_modlinkage)) != DDI_SUCCESS) { mac_fini_ops(&xx_devops); } return (rv); } int _fini(void) { int rv; if ((rv = mod_remove(&xx_modlinkage)) == DDI_SUCCESS) { mac_fini_ops(&xx_devops); } return (rv); }
mac_register_t *mac_alloc(uint_t version);
mac_alloc(9F) 関数は新しい mac_register 構造体を割り当て、この構造体へのポインタを返します。新しい構造体を mac_register() に渡す前に構造体のメンバーを初期化してください。mac_alloc() が戻る前に、MAC 専用要素が MAC 層によって初期化されます。version の値は MAC_VERSION_V1 である必要があります。
void mac_free(mac_register_t *mregp);
mac_free(9F) 関数は、以前に mac_alloc() によって割り当てられた mac_register 構造体を解放します。
int mac_register(mac_register_t *mregp, mac_handle_t *mhp);
新しいインスタンスを MAC 層に登録するために、GLDv3 ドライバは mac_register(9F) 関数をその attach (9E) エントリポイントで呼び出す必要があります。mregp 引数は、mac_register 登録情報構造体へのポインタです。成功した場合、mhp 引数は新しい MAC インスタンスの MAC ハンドルへのポインタです。このハンドルは、mac_tx_update()、mac_link_update()、mac_rx() などのほかのルーチンで必要になります。
使用例 19-2 mac_alloc()、mac_register()、および mac_free() 関数と mac_register 構造体int xx_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { mac_register_t *macp; /* ... */ if ((macp = mac_alloc(MAC_VERSION)) == NULL) { xx_error(dip, "mac_alloc failed"); goto failed; } macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; macp->m_driver = xxp; macp->m_dip = dip; macp->m_src_addr = xxp->xx_curraddr; macp->m_callbacks = &xx_m_callbacks; macp->m_min_sdu = 0; macp->m_max_sdu = ETHERMTU; macp->m_margin = VLAN_TAGSZ; if (mac_register(macp, &xxp->xx_mh) == DDI_SUCCESS) { mac_free(macp); return (DDI_SUCCESS); } /* failed to register with MAC */ mac_free(macp); failed: /* ... */ }
int mac_unregister(mac_handle_t mh);
mac_unregister(9F) 関数は、以前に mac_register() によって登録された MAC インスタンスを登録解除します。mh 引数は、mac_register() によって割り当てられた MAC ハンドルです。mac_unregister() は detach (9E) エントリポイントから呼び出してください。
使用例 19-3 mac_unregister() 関数int xx_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) { xx_t *xxp; /* driver soft state */ /* ... */ switch (cmd) { case DDI_DETACH: if (mac_unregister(xxp->xx_mh) != 0) { return (DDI_FAILURE); } /* ... */ }
このセクションで説明する構造体は、sys/mac_provider.h ヘッダーファイルで定義されます。sys/mac_ether.h および sys/mac_provider.h MAC ヘッダーファイルを GLDv3 ドライバにインクルードします。その他の MAC 関連ヘッダーファイルはインクルードしないでください。
mac_register (9S) データ構造体は、mac_alloc() によって割り当てられ、mac_register() に渡される MAC 登録情報構造体です。新しい構造体を mac_register() に渡す前に構造体のメンバーを初期化してください。mac_alloc() が戻る前に、MAC 専用要素が MAC 層によって初期化されます。構造体の m_version メンバーは MAC バージョンです。MAC バージョンを変更しないでください。構造体の m_type_ident メンバーは MAC タイプ識別子です。MAC タイプ識別子は MAC_PLUGIN_IDENT_ETHER に設定してください。mac_register 構造体の m_callbacks メンバーは、mac_callbacks 構造体のインスタンスへのポインタです。
mac_callbacks(9S) データ構造体は、デバイスドライバがそのエントリポイントを MAC 層に公開するために使用する構造体です。これらのエントリポイントは、ドライバを制御するために MAC 層によって使用されます。これらのエントリポイントは、アダプタの起動と停止、マルチキャストアドレスの管理、プロミスキュアス (promiscuous) モードの設定、アダプタの機能の照会、プロパティーの取得と設定などのタスクを実行するために使用されます。すべての必須およびオプション GLDv3 エントリポイントの一覧については、Table 19–1 を参照してください。mac_register 構造体の m_callbacks フィールドには、mac_callbacks 構造体へのポインタを指定します。
mac_callbacks 構造体の mc_callbacks メンバーは、次のフラグを組み合わせたビットマスクであり、ドライバで実装されるオプションエントリポイントを指定します。mac_callbacks 構造体のほかのメンバーは、ドライバの各エントリポイントへのポインタです。
mc_ioctl() エントリポイントが存在します。
mc_getcapab() エントリポイントが存在します。
mc_setprop() エントリポイントが存在します。
mc_getprop() エントリポイントが存在します。
mc_propinfo() エントリポイントが存在します。
すべてのプロパティーエントリポイントが存在します。MC_PROPERTIES を設定すると、MC_SETPROP、MC_GETPROP、および MC_PROPINFO の 3 つのフラグすべてを設定したことになります。
#define XX_M_CALLBACK_FLAGS \ (MC_IOCTL | MC_GETCAPAB | MC_PROPERTIES) static mac_callbacks_t xx_m_callbacks = { XX_M_CALLBACK_FLAGS, xx_m_getstat, /* mc_getstat() */ xx_m_start, /* mc_start() */ xx_m_stop, /* mc_stop() */ xx_m_promisc, /* mc_setpromisc() */ xx_m_multicst, /* mc_multicst() */ xx_m_unicst, /* mc_unicst() */ xx_m_tx, /* mc_tx() */ NULL, /* Reserved, do not use */ xx_m_ioctl, /* mc_ioctl() */ xx_m_getcapab, /* mc_getcapab() */ NULL, /* Reserved, do not use */ NULL, /* Reserved, do not use */ xx_m_setprop, /* mc_setprop() */ xx_m_getprop, /* mc_getprop() */ xx_m_propinfo /* mc_propinfo() */ };