编写适用于 Oracle® Solaris 11.2 的设备驱动程序

退出打印视图

更新时间: 2014 年 9 月
 
 

GLDv3 MAC 注册

GLDv3 为使用 MAC_PLUGIN_IDENT_ETHER 插件类型注册的驱动程序定义驱动程序 API。

GLDv3 MAC 注册过程

    GLDv3 设备驱动程序必须执行以下步骤来向 MAC 层注册:

  • 包括以下两个 MAC 头文件:sys/mac_ether.hsys/mac_provider.h。切勿在驱动程序中包含其他任何与 MAC 相关的头文件。

  • 填充 mac_callbacks 结构。

  • 在其 _init() 入口点中调用 mac_init_ops() 函数。

  • 在其 attach() 入口点中调用 mac_alloc() 函数,以分配 mac_register 结构。

  • 填充 mac_register 结构,并在其 attach() 入口点中调用 mac_register() 函数。

  • 在其 detach() 入口点中调用 mac_unregister() 函数。

  • 在其 _fini() 入口点中调用 mac_fini_ops() 函数。

  • 链接 misc/mac 依赖性:

    # ld -N"misc/mac" xx.o -o xx

GLDv3 MAC 注册函数

GLDv3 接口包括在使用 MAC 层注册过程中通告的驱动程序入口点和驱动程序调用的 MAC 入口点。

mac_init_ops()mac_fini_ops() 函数
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) 函数。

示例 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_alloc()mac_free() 函数
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 结构。

mac_register()mac_unregister() 函数
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() 等其他例程需要此句柄。

示例 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 句柄。从 detach(9E) 入口点调用 mac_unregister()

示例 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);
                }
        /* ... */
}

GLDv3 MAC 注册数据结构

本节介绍的结构是在 sys/mac_provider.h 头文件中定义的。在 GLDv3 驱动程序中包括 sys/mac_ether.hsys/mac_provider.h MAC 头文件。切勿包含其他任何于 MAC 相关的头文件。

mac_register(9S) 数据结构是 MAC 注册信息结构,由 mac_alloc() 分配,传递至 mac_register()。在将新结构传递给 mac_register() 之前初始化结构成员。在 mac_alloc() 返回之前,MAC 层会初始化 MAC 专用元素。m_version 结构成员是 MAC 版本。切勿修改 MAC 版本。m_type_ident 结构成员是 MAC 类型标识符。将 MAC 类型标识符设置为 MAC_PLUGIN_IDENT_ETHERmac_register 结构的 m_callbacks 成员是指向 mac_callbacks 结构的一个实例的指针。

mac_callbacks(9S) 数据结构是设备驱动程序用于向 MAC 层公开其入口点的结构。MAC 层使用这些入口点来控制驱动程序。这些入口点用于完成启动和停止适配器、管理多播地址、设置混杂模式、查询适配器功能、获取和设置属性等任务。有关必需和可选 GLDv3 入口点的完整列表,请参见表 19-1。在 mac_register 结构的 m_callbacks 字段中提供指向 mac_callbacks 结构的指针。

mac_callbacks 结构的 mc_callbacks 成员是一个位掩码,结合了指定驱动程序将实现哪些可选入口点的以下标志。mac_callbacks 结构的其他成员是驱动程序各入口点的指针。

MC_IOCTL

显示 mc_ioctl() 入口点。

MC_GETCAPAB

显示 mc_getcapab() 入口点。

MC_SETPROP

显示 mc_setprop() 入口点。

MC_GETPROP

显示 mc_getprop() 入口点。

MC_PROPINFO

显示 mc_propinfo() 入口点。

MC_PROPERTIES

显示所有属性入口点。设置 MC_PROPERTIES 等同于设置全部三个标志:MC_SETPROP MC_GETPROPMC_PROPINFO

示例 19-4  mac_callbacks 结构
#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() */
};