GLDv3 接口包括在使用 MAC 层注册过程中通告的驱动程序入口点和驱动程序调用的 MAC 入口点。
void mac_init_ops(struct dev_ops *ops, const char *name);
GLDv3 设备驱动程序必须在调用 mod_install(9F) 之前在其 _init(9E) 入口点中调用 mac_init_ops(9F) 函数。
void mac_fini_ops(struct dev_ops *ops);
GLDv3 设备驱动程序必须在调用 mod_remove(9F) 之后在其 _fini(9E) 入口点中调用 mac_fini_ops(9F) 函数。
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 驱动程序必须在 attach(9E) 入口点中调用 mac_register(9F) 函数。mregp 参数是指向 mac_register 注册信息结构的指针。 在成功时,mhp 参数是指向新 MAC 实例的 MAC 句柄指针。mac_tx_update()、mac_link_update () 和 mac_rx() 等其他例程需要此句柄。
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 句柄。 从 detach(9E) 入口点调用 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);
}
/* ... */
}