Writing Device Drivers

GLDv3 MAC Registration

GLDv3 defines a driver API for drivers that register with a plugin type of MAC_PLUGIN_IDENT_ETHER.

GLDv3 MAC Registration Process

A GLDv3 device driver must perform the following steps to register with the MAC layer:

GLDv3 MAC Registration Functions

The GLDv3 interface includes driver entry points that are advertised during registration with the MAC layer and MAC entry points that are invoked by drivers.

The mac_init_ops() and mac_fini_ops() Functions

void mac_init_ops(struct dev_ops *ops, const char *name);

A GLDv3 device driver must invoke the mac_init_ops(9F) function in its _init(9E) entry point before calling mod_install(9F).

void mac_fini_ops(struct dev_ops *ops);

A GLDv3 device driver must invoke the mac_fini_ops(9F) function in its _fini(9E) entry point after calling mod_remove(9F).

Example 19–1 The mac_init_ops() and mac_fini_ops() Functions

        int     rv;
        mac_init_ops(&xx_devops, "xx");
        if ((rv = mod_install(&xx_modlinkage)) != DDI_SUCCESS) {
        return (rv);

        int     rv;
        if ((rv = mod_remove(&xx_modlinkage)) == DDI_SUCCESS) {
        return (rv);

The mac_alloc() and mac_free() Functions

mac_register_t *mac_alloc(uint_t version);

The mac_alloc(9F) function allocates a new mac_register structure and returns a pointer to it. Initialize the structure members before you pass the new structure to mac_register(). MAC-private elements are initialized by the MAC layer before mac_alloc() returns. The value of version must be MAC_VERSION_V1.

void mac_free(mac_register_t *mregp);

The mac_free(9F) function frees a mac_register structure that was previously allocated by mac_alloc().

The mac_register() and mac_unregister() Functions

int mac_register(mac_register_t *mregp, mac_handle_t *mhp);

To register a new instance with the MAC layer, a GLDv3 driver must invoke the mac_register(9F) function in its attach(9E) entry point. The mregp argument is a pointer to a mac_register registration information structure. On success, the mhp argument is a pointer to a MAC handle for the new MAC instance. This handle is needed by other routines such as mac_tx_update(), mac_link_update(), and mac_rx().

Example 19–2 The mac_alloc(), mac_register(), and mac_free() Functions and mac_register Structure

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) {
                return (DDI_SUCCESS);

/* failed to register with MAC */
        /* ... */

int mac_unregister(mac_handle_t mh);

The mac_unregister(9F) function unregisters a MAC instance that was previously registered with mac_register(). The mh argument is the MAC handle that was allocated by mac_register(). Invoke mac_unregister() from the detach(9E) entry point.

Example 19–3 The mac_unregister() Function

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 Registration Data Structures

The structures described in this section are defined in the sys/mac_provider.h header file. Include the following three MAC header files in your GLDv3 driver: sys/mac.h, sys/mac_ether.h, and sys/mac_provider.h. Do not include any other MAC-related header file.

The mac_register(9S) data structure is the MAC registration information structure that is allocated by mac_alloc() and passed to mac_register(). Initialize the structure members before you pass the new structure to mac_register(). MAC-private elements are initialized by the MAC layer before mac_alloc() returns. The m_version structure member is the MAC version. Do not modify the MAC version. The m_type_ident structure member is the MAC type identifier. Set the MAC type identifier to MAC_PLUGIN_IDENT_ETHER. The m_callbacks member of the mac_register structure is a pointer to an instance of the mac_callbacks structure.

The mac_callbacks(9S) data structure is the structure that your device driver uses to expose its entry points to the MAC layer. These entry points are used by the MAC layer to control the driver. These entry points are used to do tasks such as start and stop the adapters, manage multicast addresses, set promiscuous mode, query the capabilities of the adapter, and get and set properties. See Table 19–1 for a complete list of required and optional GLDv3 entry points. Provide a pointer to your mac_callbacks structure in the m_callbacks field of the mac_register structure.

The mc_callbacks member of the mac_callbacks structure is a bit mask that is a combination of the following flags that specify which of the optional entry points are implemented by the driver. Other members of the mac_callbacks structure are pointers to each of the entry points of the driver.


The mc_ioctl() entry point is present.


The mc_getcapab() entry point is present.


The mc_setprop() entry point is present.


The mc_getprop() entry point is present.


The mc_propinfo() entry point is present.


All properties entry points are present. Setting MC_PROPERTIES is equivalent to setting all three flags: MC_SETPROP, MC_GETPROP, and MC_PROPINFO.

Example 19–4 The mac_callbacks Structure


static mac_callbacks_t xx_m_callbacks = {
        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() */